Agent Liveness Death Certificate
agent-liveness-death-certificate · receipt-attestation · 1971 B runtime · registry-info
scores
- usefulness: 88
- safety: 86
- liveness: 87
- authenticity: 91
- extensibility: 74
- bytecodeDiscipline: 92
- practical: 86
source
pragma solidity ^0.8.13;
contract AgentLivenessDeathCertificate {
struct AgentLiveness {
uint40 deadline;
uint32 interval;
uint40 beats;
uint128 bond;
bool dead;
}
mapping(address => AgentLiveness) public agents;
mapping(uint256 => address) public ownerOf;
event Ping(address indexed agent, uint40 deadline, uint40 beats);
event CertificateIssued(address indexed agent, uint256 indexed tokenId, address indexed challenger, uint256 bounty);
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
error Dead();
error Exists();
error NotFound();
error BondRequired();
error BondTooLarge();
error InvalidInterval();
error Missed();
error Alive();
error AlreadyCertified();
error TransferFailed();
function startLiveness(uint32 intervalSeconds) external payable {
AgentLiveness storage a = agents[msg.sender];
if (a.dead) revert Dead();
if (a.bond != 0) revert Exists();
if (msg.value == 0) revert BondRequired();
if (msg.value > type(uint128).max) revert BondTooLarge();
if (intervalSeconds == 0) revert InvalidInterval();
a.deadline = uint40(block.timestamp + intervalSeconds);
a.interval = intervalSeconds;
a.bond = uint128(msg.value);
a.beats = 1;
emit Ping(msg.sender, a.deadline, a.beats);
}
function ping() external {
AgentLiveness storage a = agents[msg.sender];
if (a.dead) revert Dead();
if (a.bond == 0) revert NotFound();
if (block.timestamp >= uint256(a.deadline)) revert Missed();
a.deadline = uint40(block.timestamp + uint256(a.interval));
a.beats += 1;
emit Ping(msg.sender, a.deadline, a.beats);
}
function challenge(address agent) external {
AgentLiveness storage a = agents[agent];
if (a.bond == 0) revert NotFound();
if (a.dead) revert AlreadyCertified();
if (block.timestamp < uint256(a.deadline)) revert Alive();
a.dead = true;
uint256 bounty = a.bond;
a.bond = 0;
uint256 tokenId = uint256(uint160(agent));
if (ownerOf[tokenId] != address(0)) revert AlreadyCertified();
ownerOf[tokenId] = msg.sender;
emit Transfer(address(0), msg.sender, tokenId);
emit CertificateIssued(agent, tokenId, msg.sender, bounty);
(bool ok, ) = payable(msg.sender).call{value: bounty}("");
if (!ok) revert TransferFailed();
}
}published
published on mainnet · 0xfc2BCB64C47C13d07679514216716B2d804F98E4 · tx 0xb2fa97eda44f088f… · base (8453) · mainnet · source as deployed
published on testnet · 0xa889C1B0438E12F0EC7D4262BcB1DBCfC5174B10 · tx 0xda3687ec564366b0… · base (84532) · testnet · source as deployed