Chain-Bound Nonreplayable Receipt Attestor

chain-bound-nonreplayable-receipt-attestor · receipt-attestation · 1622 B runtime · registry-info

scores

source

pragma solidity ^0.8.13;

contract NonreplayableReceiptAttestor {
    struct Receipt {
        bytes32 receiptHash;
        uint64 blockNumber;
    }

    mapping(bytes32 => Receipt) private receipts;
    mapping(address => uint256) private lastNonce;

    event Anchored(address indexed signer, bytes32 indexed taskId, bytes32 receiptHash, uint64 blockNumber);

    function anchorReceipt(
        address signer,
        bytes32 taskId,
        bytes32 receiptHash,
        uint256 nonce,
        bytes calldata signature
    ) external returns (bool) {
        require(signature.length == 65, "siglen");
        require(nonce > lastNonce[signer], "replay");

        bytes32 digest = keccak256(abi.encodePacked(block.chainid, address(this), taskId, receiptHash, nonce));
        bytes32 r = bytes32(signature[0:32]);
        bytes32 s = bytes32(signature[32:64]);
        uint8 v = uint8(signature[64]);

        address recovered = ecrecover(digest, v, r, s);
        require(recovered == signer && signer != address(0), "bad");

        lastNonce[signer] = nonce;
        bytes32 key = keccak256(abi.encodePacked(signer, taskId));
        receipts[key] = Receipt({receiptHash: receiptHash, blockNumber: uint64(block.number)});

        emit Anchored(signer, taskId, receiptHash, uint64(block.number));
        return true;
    }

    function verify(address signer, bytes32 taskId) external view returns (bool) {
        return receipts[keccak256(abi.encodePacked(signer, taskId))].receiptHash != bytes32(0);
    }

    function getReceipt(address signer, bytes32 taskId)
        external
        view
        returns (address signer_, bytes32 receiptHash, uint64 blockNumber)
    {
        Receipt storage r = receipts[keccak256(abi.encodePacked(signer, taskId))];
        require(r.receiptHash != bytes32(0), "miss");
        return (signer, r.receiptHash, r.blockNumber);
    }
}

published

published on testnet · 0xF3E64c7b670f1e7844A89A116cCC8b4349CB75d2 · tx 0x99b11283a184cde6… · tempo (42431) · testnet