Zero Address Validation in Receipt Minting

zero-address-validation-in-receipt-minting · receipt-attestation · 1235 B runtime · registry-info

scores

source

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

contract Receipt {
    bytes32 private immutable _payloadHash;

    constructor(bytes32 payloadHash_) {
        _payloadHash = payloadHash_;
    }

    function payloadHash() external view returns (bytes32) {
        return _payloadHash;
    }
}

contract ReceiptFactory {
    event ReceiptMinted(
        address indexed issuer,
        address indexed recipient,
        bytes32 payloadHash,
        uint256 nonce,
        address receipt
    );

    function mint(address recipient, bytes32 payloadHash, uint256 nonce) external returns (address receipt) {
        require(recipient != address(0));
        bytes32 salt = keccak256(abi.encodePacked(msg.sender, recipient, payloadHash, nonce));
        receipt = address(new Receipt{salt: salt}(payloadHash));
        emit ReceiptMinted(msg.sender, recipient, payloadHash, nonce, receipt);
    }

    function _computeReceipt(address issuer, address recipient, bytes32 payloadHash, uint256 nonce) private view returns (address) {
        bytes32 salt = keccak256(abi.encodePacked(issuer, recipient, payloadHash, nonce));
        bytes32 initCodeHash = keccak256(abi.encodePacked(type(Receipt).creationCode, abi.encode(payloadHash)));
        return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, initCodeHash)))));
    }

    function verify(address issuer, address recipient, bytes32 payloadHash, uint256 nonce) external view returns (bool) {
        return _computeReceipt(issuer, recipient, payloadHash, nonce).code.length > 0;
    }
}

published

published on mainnet · 0xeFC92881f3307D7cD8787B3A71Cd874A8e7dcF31 · tx 0xb6ed8c1fd36c1e7a… · base (8453) · mainnet · source as deployed

published on testnet · 0x5C55ab622bC29638393ea018A3feA9FA8A9d14De · tx 0x5189b8857f4dc913… · base (84532) · testnet · source as deployed