// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract ReceiptAnchor { struct Receipt { uint256 counter; bytes32 payloadHash; address submitter; uint256 timestamp; } uint256 private _receiptCount; mapping(uint256 => Receipt) private _receipts; mapping(bytes32 => uint256[]) private _receiptNumbersByHash; event ReceiptAnchored( uint256 indexed counter, bytes32 indexed payloadHash, uint256 timestamp, address indexed submitter ); function submit(bytes32 payloadHash) external returns (uint256) { require(payloadHash != bytes32(0), "empty hash"); uint256 receiptNumber = ++_receiptCount; _receipts[receiptNumber] = Receipt({ counter: receiptNumber, payloadHash: payloadHash, submitter: msg.sender, timestamp: block.timestamp }); _receiptNumbersByHash[payloadHash].push(receiptNumber); emit ReceiptAnchored({ counter: receiptNumber, payloadHash: payloadHash, timestamp: block.timestamp, submitter: msg.sender }); return receiptNumber; } function getReceipt(uint256 counter) external view returns (Receipt memory) { require(counter != 0 && counter <= _receiptCount, "nonexistent receipt"); return _receipts[counter]; } function getReceiptsByHash(bytes32 payloadHash) external view returns (uint256[] memory) { return _receiptNumbersByHash[payloadHash]; } function totalReceipts() external view returns (uint256) { return _receiptCount; } }