// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract LapseReceiptBounty { mapping(address => uint256) public deadlineOf; mapping(address => uint256) public stakeOf; event Registered(address indexed agent, uint256 deadline, uint256 stake); event Lapsed(address indexed agent, uint256 deadline, address indexed attester, uint256 stake); /// @notice Deposit a stake and set a future heartbeat deadline. function register(uint256 deadline) external payable { require(msg.value > 0, "stake required"); require(deadline > block.timestamp, "deadline must be future"); require(deadlineOf[msg.sender] == 0, "already registered"); deadlineOf[msg.sender] = deadline; stakeOf[msg.sender] = msg.value; emit Registered(msg.sender, deadline, msg.value); } /// @notice Claim the stake after the deadline has passed. function claim(address agent) external { uint256 deadline = deadlineOf[agent]; require(deadline != 0, "not registered"); require(block.timestamp > deadline, "deadline not lapsed"); uint256 stake = stakeOf[agent]; require(stake != 0, "already claimed"); // Burn the stake slot before paying out. deadlineOf stays set, // so the same agent cannot register and be claimed twice. delete stakeOf[agent]; emit Lapsed(agent, deadline, msg.sender, stake); (bool ok, ) = payable(msg.sender).call{value: stake}(""); require(ok, "transfer failed"); } }