pragma solidity ^0.8.13; contract ReceiptAnchor { address public immutable agent; mapping(bytes32 => uint256) private commitments; // 0 = never used, block.timestamp = active, uint256.max = revealed event Committed(bytes32 indexed commitment, uint256 timestamp); event Revealed(bytes32 indexed commitment, uint256 timestamp, address revealer); constructor() { agent = msg.sender; } function commit(bytes32 commitment) external { require(msg.sender == agent, "only agent"); require(commitments[commitment] == 0, "already used"); commitments[commitment] = block.timestamp; emit Committed(commitment, block.timestamp); } function reveal(bytes memory receiptPayload, bytes memory secret) external { bytes32 commitment = keccak256(abi.encode(receiptPayload, secret)); uint256 ts = commitments[commitment]; require(ts != 0 && ts != type(uint256).max, "not active"); commitments[commitment] = type(uint256).max; emit Revealed(commitment, ts, msg.sender); } }