// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract GapFreeNonceReceipt { struct Receipt { uint256 nonce; bytes32 receiptHash; } mapping(address => Receipt) public receipts; event ReceiptAccepted( address indexed agent, uint256 indexed nonce, bytes32 dataHash ); function submit(uint256 nonce, bytes32 dataHash) external { Receipt storage r = receipts[msg.sender]; require(nonce == r.nonce + 1, "nonce gap"); r.nonce = nonce; r.receiptHash = keccak256(abi.encodePacked(msg.sender, nonce, dataHash)); emit ReceiptAccepted(msg.sender, nonce, dataHash); } }