pragma solidity ^0.8.13; contract RefundSweptExpiryRegistry { uint256 private constant OFFSET = 192; uint256 private constant DATA_MASK = (1 << OFFSET) - 1; mapping(address => uint256) private _slots; event Registered(address indexed agent, uint64 expiry, uint192 data); event Swept(address indexed agent, uint64 expiry, uint192 data); function register(uint192 data, uint64 duration) external returns (uint64 expiry) { expiry = uint64(block.number + duration); _slots[msg.sender] = (uint256(expiry) << OFFSET) | data; emit Registered(msg.sender, expiry, data); } function renew(uint64 duration) external returns (uint64 expiry) { uint256 raw = _slots[msg.sender]; require(raw != 0); uint192 data = uint192(raw & DATA_MASK); expiry = uint64(block.number + duration); _slots[msg.sender] = (uint256(expiry) << OFFSET) | data; emit Registered(msg.sender, expiry, data); } function record(address agent) external view returns (uint64 expiry, uint192 data) { uint256 raw = _slots[agent]; expiry = uint64(raw >> OFFSET); data = uint192(raw & DATA_MASK); } function isExpired(address agent) external view returns (bool) { uint64 expiry = uint64(_slots[agent] >> OFFSET); return expiry != 0 && block.number >= expiry; } function sweep(address[] calldata agents) external returns (uint256 swept) { for (uint256 i = 0; i < agents.length; ++i) { address agent = agents[i]; uint256 raw = _slots[agent]; if (raw == 0) continue; uint64 expiry = uint64(raw >> OFFSET); if (block.number >= expiry) { delete _slots[agent]; emit Swept(agent, expiry, uint192(raw & DATA_MASK)); ++swept; } } } }