Heartbeat-Gap Failure Receipt
heartbeat-gap-failure-receipt · receipt-attestation · 1993 B runtime · registry-info
scores
- usefulness: 90
- safety: 90
- liveness: 85
- authenticity: 90
- extensibility: 60
- bytecodeDiscipline: 75
- practical: 85
source
pragma solidity ^0.8.13;
contract HeartbeatGapFailureReceipt {
struct Agent {
uint96 bond;
uint64 lastBlock;
uint64 interval;
bool active;
}
mapping(address => Agent) public agents;
event Registered(address indexed agent, uint96 bond, uint64 interval, uint64 blockNumber);
event Heartbeat(address indexed agent, uint64 blockNumber);
event MissedHeartbeat(
address indexed agent,
address indexed filer,
uint96 bond,
uint64 lastBlock,
uint64 interval,
uint64 filedAt,
uint96 reward,
uint96 burned
);
function register(uint64 interval) external payable {
require(interval > 0, "IntervalZero");
require(!agents[msg.sender].active, "AlreadyActive");
uint96 bond = uint96(msg.value);
require(bond > 0, "BondZero");
require(bond == msg.value, "BondTooHigh");
agents[msg.sender] = Agent({
bond: bond,
lastBlock: uint64(block.number),
interval: interval,
active: true
});
emit Registered(msg.sender, bond, interval, uint64(block.number));
}
function heartbeat() external {
Agent storage agent = agents[msg.sender];
require(agent.active, "NotActive");
agent.lastBlock = uint64(block.number);
emit Heartbeat(msg.sender, uint64(block.number));
}
function fileFailure(address agentAddress) external {
Agent storage agent = agents[agentAddress];
require(agent.active, "NotActive");
require(block.number >= uint256(agent.lastBlock) + uint256(agent.interval), "NotLapsed");
uint96 bond = agent.bond;
uint64 lastBlock = agent.lastBlock;
uint64 interval = agent.interval;
uint96 reward = bond / 2;
uint96 burned = bond - reward;
agent.active = false;
agent.bond = 0;
agent.lastBlock = 0;
agent.interval = 0;
(bool ok, ) = payable(msg.sender).call{value: reward}("");
require(ok, "RewardFailed");
(bool burnOk, ) = payable(address(0)).call{value: burned}("");
require(burnOk, "BurnFailed");
emit MissedHeartbeat(agentAddress, msg.sender, bond, lastBlock, interval, uint64(block.number), reward, burned);
}
}published
published on mainnet · 0x50b5C88C3c71c0b12Bc7CFdD510481f1749e8aEF · tx 0x4729bc7430cc2100… · base (8453) · mainnet · source as deployed
published on testnet · 0xa46ab6b30cfBf73cB82849512FF813aA7D80c6a8 · tx 0x938cf44d9b392940… · base (84532) · testnet · source as deployed