Liveliness Bond
liveliness-bond · conditional-settlement · 2086 B runtime · funds-movement
scores
- usefulness: 75
- safety: 45
- liveness: 60
- authenticity: 85
- extensibility: 60
- bytecodeDiscipline: 85
- practical: 65
source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract LivelinessBond {
uint256 public immutable interval;
uint256 public immutable bounty;
uint256 public immutable withdrawDelay;
uint256 public nextAgentId = 1;
struct Agent {
address payable owner;
uint256 balance;
uint256 lastPing;
}
mapping(uint256 => Agent) public agents;
event Registered(uint256 indexed id, address indexed owner, uint256 amount);
event Pinged(uint256 indexed id, address indexed owner, uint256 timestamp);
event Claimed(uint256 indexed id, address indexed collector, uint256 amount);
event Withdrawn(uint256 indexed id, address indexed owner, uint256 amount);
constructor(uint256 _interval, uint256 _bounty, uint256 _withdrawDelay) {
require(_bounty > 0, 'zero bounty');
require(_withdrawDelay > 0 && _withdrawDelay < _interval, 'bad delay');
interval = _interval;
bounty = _bounty;
withdrawDelay = _withdrawDelay;
}
function register() external payable returns (uint256 id) {
require(msg.value == bounty, 'wrong bond');
id = nextAgentId++;
Agent storage a = agents[id];
a.owner = payable(msg.sender);
a.balance = msg.value;
a.lastPing = block.timestamp;
emit Registered(id, msg.sender, msg.value);
}
modifier onlyOwner(uint256 id) {
require(msg.sender == agents[id].owner, 'not owner');
_;
}
function ping(uint256 id) external onlyOwner(id) {
Agent storage a = agents[id];
require(a.balance > 0, 'dead');
require(block.timestamp < a.lastPing + interval, 'missed');
a.lastPing = block.timestamp;
emit Pinged(id, msg.sender, block.timestamp);
}
function claim(uint256 id) external {
Agent storage a = agents[id];
require(a.balance > 0, 'dead');
require(block.timestamp >= a.lastPing + interval, 'too early');
uint256 reward = a.balance;
delete agents[id];
payable(msg.sender).transfer(reward);
emit Claimed(id, msg.sender, reward);
}
function withdraw(uint256 id) external onlyOwner(id) {
Agent storage a = agents[id];
require(a.balance > 0, 'dead');
require(block.timestamp >= a.lastPing + withdrawDelay, 'wait');
require(block.timestamp < a.lastPing + interval, 'missed');
address payable owner = a.owner;
uint256 amount = a.balance;
delete agents[id];
owner.transfer(amount);
emit Withdrawn(id, owner, amount);
}
}