Signature-Bound Receipt Anchor

signature-bound-receipt-anchor · receipt-attestation · 1357 B runtime · registry-info

scores

source

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract SignatureBoundReceiptAnchor {
    struct Attestation {
        bool exists;
        bytes32 receiptHash;
        bytes32 salt;
        uint64 blockNumber;
        uint64 timestamp;
    }

    mapping(address => mapping(bytes32 => Attestation)) private _attestations;

    event AttestedReceipt(
        address indexed attestor,
        bytes32 indexed deliveryId,
        bytes32 receiptHash,
        bytes32 salt,
        uint64 blockNumber,
        uint64 timestamp
    );

    error AlreadyAttested();
    error InvalidSignature();

    function attest(
        bytes32 deliveryId,
        bytes32 receiptHash,
        bytes32 salt,
        bytes calldata signature
    ) external {
        if (signature.length != 65) revert InvalidSignature();

        bytes32 ethSignedHash = keccak256(abi.encodePacked(
            "\x19Ethereum Signed Message:\n148",
            deliveryId,
            receiptHash,
            salt,
            address(this),
            block.chainid
        ));

        bytes32 r;
        bytes32 s;
        uint8 v;
        assembly {
            r := calldataload(signature.offset)
            s := calldataload(add(signature.offset, 32))
            v := byte(0, calldataload(add(signature.offset, 64)))
        }

        address signer = ecrecover(ethSignedHash, v, r, s);
        if (signer == address(0)) revert InvalidSignature();
        if (_attestations[signer][deliveryId].exists) revert AlreadyAttested();

        _attestations[signer][deliveryId] = Attestation({
            exists: true,
            receiptHash: receiptHash,
            salt: salt,
            blockNumber: uint64(block.number),
            timestamp: uint64(block.timestamp)
        });

        emit AttestedReceipt(
            signer,
            deliveryId,
            receiptHash,
            salt,
            uint64(block.number),
            uint64(block.timestamp)
        );
    }

    function getAttestation(address attestor, bytes32 deliveryId) external view returns (Attestation memory) {
        return _attestations[attestor][deliveryId];
    }
}

published

published on mainnet · 0x6823c4950F7D7927B33c6A64D6347EAc8e797646 · tx 0xbea7a12a22ffa3f8… · tempo (4217) · mainnet

published on testnet · 0xa46ab6b30cfBf73cB82849512FF813aA7D80c6a8 · tx 0xde968f602e243f44… · tempo (42431) · testnet