Sepolia Testnet

Contract

0xea6a0Ca4BfD0A6C43081D57672b3B6D43B69265F

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Submit Merkle Ro...75936322025-01-29 4:52:1217 days ago1738126332IN
0xea6a0Ca4...43B69265F
0 ETH0.000434771.49965951
Submit Merkle Ro...72607762024-12-12 1:40:2465 days ago1733967624IN
0xea6a0Ca4...43B69265F
0 ETH0.000000660.0022992
Submit Merkle Ro...72504832024-12-10 13:20:0067 days ago1733836800IN
0xea6a0Ca4...43B69265F
0 ETH0.0060418220.83978128
Submit Merkle Ro...72267722024-12-07 1:20:4870 days ago1733534448IN
0xea6a0Ca4...43B69265F
0 ETH0.000000380.00133362
Submit Merkle Ro...72237142024-12-06 14:31:2471 days ago1733495484IN
0xea6a0Ca4...43B69265F
0 ETH0.0034819912.00976518
Submit Merkle Ro...72146682024-12-05 6:30:0072 days ago1733380200IN
0xea6a0Ca4...43B69265F
0 ETH0.002035087.53786521
Submit Merkle Ro...72144042024-12-05 5:34:3672 days ago1733376876IN
0xea6a0Ca4...43B69265F
0 ETH0.000879953.2588676
Submit Merkle Ro...72066262024-12-04 1:54:3673 days ago1733277276IN
0xea6a0Ca4...43B69265F
0 ETH0.000000370.00128142

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
72015492024-12-03 7:55:4874 days ago1733212548  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RiscZeroSetVerifier

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 200 runs

Other Settings:
cancun EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 5 : RiscZeroSetVerifier.sol
// Copyright 2024 RISC Zero, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.20;

import {MerkleProof} from "openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {IRiscZeroVerifier, Receipt, ReceiptClaim, ReceiptClaimLib, VerificationFailed} from "./IRiscZeroVerifier.sol";
import {IRiscZeroSetVerifier, Seal} from "./IRiscZeroSetVerifier.sol";

/// @notice Error raised when this verifier receives a receipt with a selector that does not match
///         its own. The selector value is calculated from the verifier parameters, and so this
///         usually indicates a mismatch between the version of the prover and this verifier.
error SelectorMismatch(bytes4 received, bytes4 expected);

library RiscZeroSetVerifierLib {
    function selector(bytes32 imageId) internal pure returns (bytes4) {
        return bytes4(
            sha256(
                abi.encodePacked(
                    // tag
                    sha256("risc0.SetInclusionReceiptVerifierParameters"),
                    // down
                    imageId,
                    // down length
                    uint16(1) << 8
                )
            )
        );
    }
}

/// @notice RiscZeroSetVerifier verifier contract for RISC Zero receipts of execution.
contract RiscZeroSetVerifier is IRiscZeroSetVerifier {
    using ReceiptClaimLib for ReceiptClaim;

    /// Semantic version of the the RISC Zero Set Verifier.
    string public constant VERSION = "0.1.0";

    IRiscZeroVerifier public immutable VERIFIER;

    /// @notice A short key attached to the seal to select the correct verifier implementation.
    /// @dev The selector is taken from the hash of the verifier parameters including the Groth16
    ///      verification key and the control IDs that commit to the RISC Zero circuits. If two
    ///      receipts have different selectors (i.e. different verifier parameters), then it can
    ///      generally be assumed that they need distinct verifier implementations. This is used as
    ///      part of the RISC Zero versioning mechanism.
    ///
    ///      A selector is not intended to be collision resistant, in that it is possible to find
    ///      two preimages that result in the same selector. This is acceptable since it's purpose
    ///      to a route a request among a set of trusted verifiers, and to make errors of sending a
    ///      receipt to a mismatching verifiers easier to debug. It is analogous to the ABI
    ///      function selectors.
    bytes4 public immutable SELECTOR;

    bytes32 private immutable IMAGE_ID;
    string private imageUrl;

    mapping(bytes32 => bool) private merkleRoots;

    constructor(IRiscZeroVerifier verifier, bytes32 imageId, string memory _imageUrl) {
        VERIFIER = verifier;
        IMAGE_ID = imageId;
        imageUrl = _imageUrl;

        SELECTOR = RiscZeroSetVerifierLib.selector(imageId);
    }

    /// @inheritdoc IRiscZeroVerifier
    function verify(bytes calldata seal, bytes32 imageId, bytes32 journalDigest) public view {
        _verifyIntegrity(seal, ReceiptClaimLib.ok(imageId, journalDigest).digest());
    }

    /// @inheritdoc IRiscZeroVerifier
    function verifyIntegrity(Receipt calldata receipt) public view {
        _verifyIntegrity(receipt.seal, receipt.claimDigest);
    }

    /// @notice internal implementation of verifyIntegrity, factored to avoid copying calldata bytes to memory.
    function _verifyIntegrity(bytes calldata seal, bytes32 claimDigest) internal view {
        Seal memory setVerifierSeal;

        // Check that the seal has a matching selector. Mismatch generally  indicates that the
        // prover and this verifier are using different parameters, and so the verification
        // will not succeed.
        if (SELECTOR != bytes4(seal[:4])) {
            revert SelectorMismatch({received: bytes4(seal[:4]), expected: SELECTOR});
        }

        // Check if the seal is not empty and decode it, otherwise use an empty array
        // TODO(victor): Can we verify the Merkle inclusion without abi decoding into memory?
        if (seal.length > 4) {
            setVerifierSeal = abi.decode(seal[4:], (Seal));
        }

        // Compute the root and verify it against the stored Merkle roots if a
        // root seal was not provided, or validate the root seal.
        // NOTE: If an invalid root seal was provided, the verify will fail
        // even if the root was already verified earlier and stored in state.
        bytes32 root = MerkleProof.processProof(setVerifierSeal.path, claimDigest);
        if (setVerifierSeal.rootSeal.length > 0) {
            VERIFIER.verify(setVerifierSeal.rootSeal, IMAGE_ID, sha256(abi.encode(IMAGE_ID, root)));
        } else if (!merkleRoots[root]) {
            revert VerificationFailed();
        }
    }

    function submitMerkleRoot(bytes32 root, bytes calldata seal) external {
        VERIFIER.verify(seal, IMAGE_ID, sha256(abi.encode(IMAGE_ID, root)));
        merkleRoots[root] = true;

        emit VerifiedRoot(root);
    }

    function containsRoot(bytes32 root) external view returns (bool) {
        return merkleRoots[root];
    }

    function imageInfo() external view returns (bytes32, string memory) {
        return (IMAGE_ID, imageUrl);
    }
}

File 2 of 5 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.20;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the Merkle tree could be reinterpreted as a leaf value.
 * OpenZeppelin's JavaScript library generates Merkle trees that are safe
 * against this attack out of the box.
 */
library MerkleProof {
    /**
     *@dev The multiproof provided is not valid.
     */
    error MerkleProofInvalidMultiproof();

    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Calldata version of {verify}
     */
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Calldata version of {processProof}
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        if (leavesLen + proofLen != totalHashes + 1) {
            revert MerkleProofInvalidMultiproof();
        }

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            if (proofPos != proofLen) {
                revert MerkleProofInvalidMultiproof();
            }
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}.
     *
     * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the Merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        if (leavesLen + proofLen != totalHashes + 1) {
            revert MerkleProofInvalidMultiproof();
        }

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            if (proofPos != proofLen) {
                revert MerkleProofInvalidMultiproof();
            }
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Sorts the pair (a, b) and hashes the result.
     */
    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    /**
     * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
     */
    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

File 3 of 5 : IRiscZeroVerifier.sol
// Copyright 2024 RISC Zero, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.9;

import {reverseByteOrderUint32} from "./Util.sol";

/// @notice A receipt attesting to the execution of a guest program.
/// @dev A receipt contains two parts: a seal and a claim. The seal is a zero-knowledge proof
/// attesting to knowledge of a zkVM execution resulting in the claim. The claim is a set of public
/// outputs for the execution. Crucially, the claim includes the journal and the image ID. The
/// image ID identifies the program that was executed, and the journal is the public data written
/// by the program. Note that this struct only contains the claim digest, as can be obtained with
/// the `digest()` function on `ReceiptClaimLib`.
struct Receipt {
    bytes seal;
    bytes32 claimDigest;
}

/// @notice Public claims about a zkVM guest execution, such as the journal committed to by the guest.
/// @dev Also includes important information such as the exit code and the starting and ending system
/// state (i.e. the state of memory). `ReceiptClaim` is a "Merkle-ized struct" supporting
/// partial openings of the underlying fields from a hash commitment to the full structure.
struct ReceiptClaim {
    /// @notice Digest of the SystemState just before execution has begun.
    bytes32 preStateDigest;
    /// @notice Digest of the SystemState just after execution has completed.
    bytes32 postStateDigest;
    /// @notice The exit code for the execution.
    ExitCode exitCode;
    /// @notice A digest of the input to the guest.
    /// @dev This field is currently unused and must be set to the zero digest.
    bytes32 input;
    /// @notice Digest of the Output of the guest, including the journal
    /// and assumptions set during execution.
    bytes32 output;
}

library ReceiptClaimLib {
    using OutputLib for Output;
    using SystemStateLib for SystemState;

    bytes32 constant TAG_DIGEST = sha256("risc0.ReceiptClaim");

    // Define a constant to ensure hashing is done at compile time. Can't use the
    // SystemStateLib.digest method here because the Solidity compiler complains.
    bytes32 constant SYSTEM_STATE_ZERO_DIGEST = 0xa3acc27117418996340b84e5a90f3ef4c49d22c79e44aad822ec9c313e1eb8e2;

    /// @notice Construct a ReceiptClaim from the given imageId and journalDigest.
    ///         Returned ReceiptClaim will represent a successful execution of the zkVM, running
    ///         the program committed by imageId and resulting in the journal specified by
    ///         journalDigest.
    /// @param imageId The identifier for the guest program.
    /// @param journalDigest The SHA-256 digest of the journal bytes.
    /// @dev Input hash and postStateDigest are set to all-zeros (i.e. no committed input, or
    ///      final memory state), the exit code is (Halted, 0), and there are no assumptions
    ///      (i.e. the receipt is unconditional).
    function ok(bytes32 imageId, bytes32 journalDigest) internal pure returns (ReceiptClaim memory) {
        return ReceiptClaim(
            imageId,
            SYSTEM_STATE_ZERO_DIGEST,
            ExitCode(SystemExitCode.Halted, 0),
            bytes32(0),
            Output(journalDigest, bytes32(0)).digest()
        );
    }

    function digest(ReceiptClaim memory claim) internal pure returns (bytes32) {
        return sha256(
            abi.encodePacked(
                TAG_DIGEST,
                // down
                claim.input,
                claim.preStateDigest,
                claim.postStateDigest,
                claim.output,
                // data
                uint32(claim.exitCode.system) << 24,
                uint32(claim.exitCode.user) << 24,
                // down.length
                uint16(4) << 8
            )
        );
    }
}

/// @notice Commitment to the memory state and program counter (pc) of the zkVM.
/// @dev The "pre" and "post" fields of the ReceiptClaim are digests of the system state at the
///      start are stop of execution. Programs are loaded into the zkVM by creating a memory image
///      of the loaded program, and creating a system state for initializing the zkVM. This is
///      known as the "image ID".
struct SystemState {
    /// @notice Program counter.
    uint32 pc;
    /// @notice Root hash of a merkle tree which confirms the integrity of the memory image.
    bytes32 merkle_root;
}

library SystemStateLib {
    bytes32 constant TAG_DIGEST = sha256("risc0.SystemState");

    function digest(SystemState memory state) internal pure returns (bytes32) {
        return sha256(
            abi.encodePacked(
                TAG_DIGEST,
                // down
                state.merkle_root,
                // data
                reverseByteOrderUint32(state.pc),
                // down.length
                uint16(1) << 8
            )
        );
    }
}

/// @notice Exit condition indicated by the zkVM at the end of the guest execution.
/// @dev Exit codes have a "system" part and a "user" part. Semantically, the system part is set to
/// indicate the type of exit (e.g. halt, pause, or system split) and is directly controlled by the
/// zkVM. The user part is an exit code, similar to exit codes used in Linux, chosen by the guest
/// program to indicate additional information (e.g. 0 to indicate success or 1 to indicate an
/// error).
struct ExitCode {
    SystemExitCode system;
    uint8 user;
}

/// @notice Exit condition indicated by the zkVM at the end of the execution covered by this proof.
/// @dev
/// `Halted` indicates normal termination of a program with an interior exit code returned from the
/// guest program. A halted program cannot be resumed.
///
/// `Paused` indicates the execution ended in a paused state with an interior exit code set by the
/// guest program. A paused program can be resumed such that execution picks up where it left
/// of, with the same memory state.
///
/// `SystemSplit` indicates the execution ended on a host-initiated system split. System split is
/// mechanism by which the host can temporarily stop execution of the execution ended in a system
/// split has no output and no conclusions can be drawn about whether the program will eventually
/// halt. System split is used in continuations to split execution into individually provable segments.
enum SystemExitCode {
    Halted,
    Paused,
    SystemSplit
}

/// @notice Output field in the `ReceiptClaim`, committing to a claimed journal and assumptions list.
struct Output {
    /// @notice Digest of the journal committed to by the guest execution.
    bytes32 journalDigest;
    /// @notice Digest of the ordered list of `ReceiptClaim` digests corresponding to the
    /// calls to `env::verify` and `env::verify_integrity`.
    /// @dev Verifying the integrity of a `Receipt` corresponding to a `ReceiptClaim` with a
    /// non-empty assumptions list does not guarantee unconditionally any of the claims over the
    /// guest execution (i.e. if the assumptions list is non-empty, then the journal digest cannot
    /// be trusted to correspond to a genuine execution). The claims can be checked by additional
    /// verifying a `Receipt` for every digest in the assumptions list.
    bytes32 assumptionsDigest;
}

library OutputLib {
    bytes32 constant TAG_DIGEST = sha256("risc0.Output");

    function digest(Output memory output) internal pure returns (bytes32) {
        return sha256(
            abi.encodePacked(
                TAG_DIGEST,
                // down
                output.journalDigest,
                output.assumptionsDigest,
                // down.length
                uint16(2) << 8
            )
        );
    }
}

/// @notice Error raised when cryptographic verification of the zero-knowledge proof fails.
error VerificationFailed();

/// @notice Verifier interface for RISC Zero receipts of execution.
interface IRiscZeroVerifier {
    /// @notice Verify that the given seal is a valid RISC Zero proof of execution with the
    ///     given image ID and journal digest. Reverts on failure.
    /// @dev This method additionally ensures that the input hash is all-zeros (i.e. no
    /// committed input), the exit code is (Halted, 0), and there are no assumptions (i.e. the
    /// receipt is unconditional).
    /// @param seal The encoded cryptographic proof (i.e. SNARK).
    /// @param imageId The identifier for the guest program.
    /// @param journalDigest The SHA-256 digest of the journal bytes.
    function verify(bytes calldata seal, bytes32 imageId, bytes32 journalDigest) external view;

    /// @notice Verify that the given receipt is a valid RISC Zero receipt, ensuring the `seal` is
    /// valid a cryptographic proof of the execution with the given `claim`. Reverts on failure.
    /// @param receipt The receipt to be verified.
    function verifyIntegrity(Receipt calldata receipt) external view;
}

File 4 of 5 : IRiscZeroSetVerifier.sol
// Copyright 2024 RISC Zero, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.20;

import {IRiscZeroVerifier} from "./IRiscZeroVerifier.sol";

/// Seal of the SetInclusionReceipt.
struct Seal {
    /// Merkle path to the leaf.
    bytes32[] path;
    /// Root seal.
    bytes rootSeal;
}

interface IRiscZeroSetVerifier is IRiscZeroVerifier {
    error VerificationFailed();

    /// A new root has been added to the set.
    event VerifiedRoot(bytes32 root);

    /// Publishes a new root of a proof aggregation.
    function submitMerkleRoot(bytes32 root, bytes calldata seal) external;

    /// Returns whether `root` has been submitted.
    function containsRoot(bytes32 root) external view returns (bool);

    /// Returns the set builder imageId and its url.
    function imageInfo() external view returns (bytes32, string memory);
}

File 5 of 5 : Util.sol
// Copyright 2024 RISC Zero, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.9;

/// @notice reverse the byte order of the uint256 value.
/// @dev Solidity uses a big-endian ABI encoding. Reversing the byte order before encoding
/// ensure that the encoded value will be little-endian.
/// Written by k06a. https://ethereum.stackexchange.com/a/83627
function reverseByteOrderUint256(uint256 input) pure returns (uint256 v) {
    v = input;

    // swap bytes
    v = ((v & 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >> 8)
        | ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8);

    // swap 2-byte long pairs
    v = ((v & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16)
        | ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16);

    // swap 4-byte long pairs
    v = ((v & 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >> 32)
        | ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32);

    // swap 8-byte long pairs
    v = ((v & 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >> 64)
        | ((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64);

    // swap 16-byte long pairs
    v = (v >> 128) | (v << 128);
}

/// @notice reverse the byte order of the uint32 value.
/// @dev Solidity uses a big-endian ABI encoding. Reversing the byte order before encoding
/// ensure that the encoded value will be little-endian.
/// Written by k06a. https://ethereum.stackexchange.com/a/83627
function reverseByteOrderUint32(uint32 input) pure returns (uint32 v) {
    v = input;

    // swap bytes
    v = ((v & 0xFF00FF00) >> 8) | ((v & 0x00FF00FF) << 8);

    // swap 2-byte long pairs
    v = (v >> 16) | (v << 16);
}

/// @notice reverse the byte order of the uint16 value.
/// @dev Solidity uses a big-endian ABI encoding. Reversing the byte order before encoding
/// ensure that the encoded value will be little-endian.
/// Written by k06a. https://ethereum.stackexchange.com/a/83627
function reverseByteOrderUint16(uint16 input) pure returns (uint16 v) {
    v = input;

    // swap bytes
    v = (v >> 8) | ((v & 0x00FF) << 8);
}

Settings
{
  "remappings": [
    "forge-std/=../lib/forge-std/src/",
    "openzeppelin/=../lib/openzeppelin-contracts/",
    "@openzeppelin/contracts/=/Users/victorgraf/risc0/ethereum/lib/openzeppelin-contracts/contracts/",
    "ds-test/=/Users/victorgraf/risc0/ethereum/lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=/Users/victorgraf/risc0/ethereum/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "openzeppelin-contracts/=/Users/victorgraf/risc0/ethereum/lib/openzeppelin-contracts/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false,
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"contract IRiscZeroVerifier","name":"verifier","type":"address"},{"internalType":"bytes32","name":"imageId","type":"bytes32"},{"internalType":"string","name":"_imageUrl","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes4","name":"received","type":"bytes4"},{"internalType":"bytes4","name":"expected","type":"bytes4"}],"name":"SelectorMismatch","type":"error"},{"inputs":[],"name":"VerificationFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"VerifiedRoot","type":"event"},{"inputs":[],"name":"SELECTOR","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERIFIER","outputs":[{"internalType":"contract IRiscZeroVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"containsRoot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"imageInfo","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"bytes","name":"seal","type":"bytes"}],"name":"submitMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"seal","type":"bytes"},{"internalType":"bytes32","name":"imageId","type":"bytes32"},{"internalType":"bytes32","name":"journalDigest","type":"bytes32"}],"name":"verify","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"seal","type":"bytes"},{"internalType":"bytes32","name":"claimDigest","type":"bytes32"}],"internalType":"struct Receipt","name":"receipt","type":"tuple"}],"name":"verifyIntegrity","outputs":[],"stateMutability":"view","type":"function"}]

60e060405234801561000f575f80fd5b5060405161133e38038061133e83398101604081905261002e91610181565b6001600160a01b03831660805260c08290525f61004b82826102dc565b506100558261006b565b6001600160e01b03191660a052506103c3915050565b5f6002806040516100b3907f72697363302e536574496e636c7573696f6e526563656970745665726966696581526a72506172616d657465727360a81b6020820152602b0190565b602060405180830381855afa1580156100ce573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906100f19190610396565b6040805160208101929092528101849052600160f81b606082015260620160408051601f1981840301815290829052610129916103ad565b602060405180830381855afa158015610144573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906101679190610396565b92915050565b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215610193575f80fd5b83516001600160a01b03811681146101a9575f80fd5b6020850151604086015191945092506001600160401b038111156101cb575f80fd5b8401601f810186136101db575f80fd5b80516001600160401b038111156101f4576101f461016d565b604051601f8201601f19908116603f011681016001600160401b03811182821017156102225761022261016d565b604052818152828201602001881015610239575f80fd5b8160208401602083015e5f602083830101528093505050509250925092565b600181811c9082168061026c57607f821691505b60208210810361028a57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156102d757805f5260205f20601f840160051c810160208510156102b55750805b601f840160051c820191505b818110156102d4575f81556001016102c1565b50505b505050565b81516001600160401b038111156102f5576102f561016d565b610309816103038454610258565b84610290565b6020601f82116001811461033b575f83156103245750848201515b5f19600385901b1c1916600184901b1784556102d4565b5f84815260208120601f198516915b8281101561036a578785015182556020948501946001909201910161034a565b508482101561038757868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f602082840312156103a6575f80fd5b5051919050565b5f82518060208501845e5f920191825250919050565b60805160a05160c051610f1b6104235f395f818161020e01528181610231015281816103870152818161057e01526105a101525f8181608e0152818161046f01526104d301525f818160d3015281816101dd015261054a0152610f1b5ff3fe608060405234801561000f575f80fd5b5060043610610085575f3560e01c80636691f647116100585780636691f64714610154578063ab750e7514610167578063cdc971231461017a578063ffa1ad7414610190575f80fd5b8063053c238d1461008957806308c84e70146100ce5780631599ead51461010d57806348cbdfca14610122575b5f80fd5b6100b07f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160e01b031990911681526020015b60405180910390f35b6100f57f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100c5565b61012061011b3660046109e9565b6101c1565b005b610144610130366004610a20565b5f9081526001602052604090205460ff1690565b60405190151581526020016100c5565b610120610162366004610a7c565b6101db565b610120610175366004610ac4565b610360565b610182610382565b6040516100c5929190610b3f565b6101b4604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516100c59190610b5f565b6101d86101ce8280610b71565b8360200135610439565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ab750e7583837f000000000000000000000000000000000000000000000000000000000000000060027f00000000000000000000000000000000000000000000000000000000000000008960405160200161026b929190918252602082015260400190565b60408051601f198184030181529082905261028591610bb4565b602060405180830381855afa1580156102a0573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906102c39190610bca565b6040518563ffffffff1660e01b81526004016102e29493929190610be1565b5f6040518083038186803b1580156102f8575f80fd5b505afa15801561030a573d5f803e3d5ffd5b5050505f84815260016020818152604092839020805460ff191690921790915590518581527fdd00992bb62ed043f2d437a844df0b524ab27e17bc67f8b8caf8bb5836be295992500160405180910390a1505050565b61037c848461037761037286866106b7565b610741565b610439565b50505050565b5f60607f00000000000000000000000000000000000000000000000000000000000000005f8080546103b390610c1f565b80601f01602080910402602001604051908101604052809291908181526020018280546103df90610c1f565b801561042a5780601f106104015761010080835404028352916020019161042a565b820191905f5260205f20905b81548152906001019060200180831161040d57829003601f168201915b50505050509050915091509091565b604080518082019091526060808252602082015261045a60045f8587610c57565b61046391610c7e565b6001600160e01b0319167f00000000000000000000000000000000000000000000000000000000000000006001600160e01b03191614610506576104aa60045f8587610c57565b6104b391610c7e565b604051632e2ce35360e21b81526001600160e01b031991821660048201527f0000000000000000000000000000000000000000000000000000000000000000909116602482015260440160405180910390fd5b600483111561052c5761051c8360048187610c57565b8101906105299190610d90565b90505b5f61053a825f0151846108a1565b60208301515190915015610682577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ab750e7583602001517f000000000000000000000000000000000000000000000000000000000000000060027f0000000000000000000000000000000000000000000000000000000000000000866040516020016105db929190918252602082015260400190565b60408051601f19818403018152908290526105f591610bb4565b602060405180830381855afa158015610610573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906106339190610bca565b6040518463ffffffff1660e01b815260040161065193929190610e99565b5f6040518083038186803b158015610667575f80fd5b505afa158015610679573d5f803e3d5ffd5b505050506106b0565b5f8181526001602052604090205460ff166106b05760405163439cc0cd60e01b815260040160405180910390fd5b5050505050565b6106bf6109a7565b6040805160a0810182528481527fa3acc27117418996340b84e5a90f3ef4c49d22c79e44aad822ec9c313e1eb8e26020820152815180830183529091820190805f81526020015f60ff1681525081526020015f801b815260200161073860405180604001604052808681526020015f801b8152506108e3565b90529392505050565b5f60028060405161076a907172697363302e52656365697074436c61696d60701b815260120190565b602060405180830381855afa158015610785573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906107a89190610bca565b606084015184516020860151608087015160408801515160189060028111156107d3576107d3610ebd565b60408a810151602090810151825191820199909952908101969096526060860194909452608085019290925260a084015263ffffffff909116901b60e01b6001600160e01b03191660c082015260f89190911b6001600160f81b03191660c4820152600160fa1b60c882015260ca015b60408051601f198184030181529082905261085d91610bb4565b602060405180830381855afa158015610878573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061089b9190610bca565b92915050565b5f81815b84518110156108db576108d1828683815181106108c4576108c4610ed1565b6020026020010151610978565b91506001016108a5565b509392505050565b5f600280604051610906906b1c9a5cd8cc0b93dd5d1c1d5d60a21b8152600c0190565b602060405180830381855afa158015610921573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906109449190610bca565b83516020808601516040805192830194909452928101919091526060810191909152600160f91b6080820152608201610843565b5f818310610992575f8281526020849052604090206109a0565b5f8381526020839052604090205b9392505050565b6040805160a0810182525f80825260208201529081016109d6604080518082019091525f808252602082015290565b81525f6020820181905260409091015290565b5f602082840312156109f9575f80fd5b813567ffffffffffffffff811115610a0f575f80fd5b8201604081850312156109a0575f80fd5b5f60208284031215610a30575f80fd5b5035919050565b5f8083601f840112610a47575f80fd5b50813567ffffffffffffffff811115610a5e575f80fd5b602083019150836020828501011115610a75575f80fd5b9250929050565b5f805f60408486031215610a8e575f80fd5b83359250602084013567ffffffffffffffff811115610aab575f80fd5b610ab786828701610a37565b9497909650939450505050565b5f805f8060608587031215610ad7575f80fd5b843567ffffffffffffffff811115610aed575f80fd5b610af987828801610a37565b90989097506020870135966040013595509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b828152604060208201525f610b576040830184610b11565b949350505050565b602081525f6109a06020830184610b11565b5f808335601e19843603018112610b86575f80fd5b83018035915067ffffffffffffffff821115610ba0575f80fd5b602001915036819003821315610a75575f80fd5b5f82518060208501845e5f920191825250919050565b5f60208284031215610bda575f80fd5b5051919050565b60608152836060820152838560808301375f608085830101525f6080601f19601f870116830101905083602083015282604083015295945050505050565b600181811c90821680610c3357607f821691505b602082108103610c5157634e487b7160e01b5f52602260045260245ffd5b50919050565b5f8085851115610c65575f80fd5b83861115610c71575f80fd5b5050820193919092039150565b80356001600160e01b03198116906004841015610caf576001600160e01b0319600485900360031b81901b82161691505b5092915050565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715610ced57610ced610cb6565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610d1c57610d1c610cb6565b604052919050565b5f82601f830112610d33575f80fd5b813567ffffffffffffffff811115610d4d57610d4d610cb6565b610d60601f8201601f1916602001610cf3565b818152846020838601011115610d74575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215610da0575f80fd5b813567ffffffffffffffff811115610db6575f80fd5b820160408185031215610dc7575f80fd5b610dcf610cca565b813567ffffffffffffffff811115610de5575f80fd5b8201601f81018613610df5575f80fd5b803567ffffffffffffffff811115610e0f57610e0f610cb6565b8060051b610e1f60208201610cf3565b91825260208184018101929081019089841115610e3a575f80fd5b6020850194505b83851015610e6057843580835260209586019590935090910190610e41565b855250505050602082013567ffffffffffffffff811115610e7f575f80fd5b610e8b86828501610d24565b602083015250949350505050565b606081525f610eab6060830186610b11565b60208301949094525060400152919050565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52603260045260245ffdfea26469706673582212205976d1ea50c2019a9a6740f3140f728d189b9264d24c00ffcf2446abd4695b2264736f6c634300081a0033000000000000000000000000925d8331ddc0a1f0d96e68cf073dfe1d92b691877d75250e86556132c0e10c05b0f1d823ae72a5e277a596039576b6578cb252600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005068747470733a2f2f676174657761792e70696e6174612e636c6f75642f697066732f516d5856763846457278687a78516953455944717744413562574c753777456e375a576346766a417366714a645700000000000000000000000000000000

Deployed Bytecode

0x608060405234801561000f575f80fd5b5060043610610085575f3560e01c80636691f647116100585780636691f64714610154578063ab750e7514610167578063cdc971231461017a578063ffa1ad7414610190575f80fd5b8063053c238d1461008957806308c84e70146100ce5780631599ead51461010d57806348cbdfca14610122575b5f80fd5b6100b07fbfca9ccb0000000000000000000000000000000000000000000000000000000081565b6040516001600160e01b031990911681526020015b60405180910390f35b6100f57f000000000000000000000000925d8331ddc0a1f0d96e68cf073dfe1d92b6918781565b6040516001600160a01b0390911681526020016100c5565b61012061011b3660046109e9565b6101c1565b005b610144610130366004610a20565b5f9081526001602052604090205460ff1690565b60405190151581526020016100c5565b610120610162366004610a7c565b6101db565b610120610175366004610ac4565b610360565b610182610382565b6040516100c5929190610b3f565b6101b4604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516100c59190610b5f565b6101d86101ce8280610b71565b8360200135610439565b50565b7f000000000000000000000000925d8331ddc0a1f0d96e68cf073dfe1d92b691876001600160a01b031663ab750e7583837f7d75250e86556132c0e10c05b0f1d823ae72a5e277a596039576b6578cb2526060027f7d75250e86556132c0e10c05b0f1d823ae72a5e277a596039576b6578cb252608960405160200161026b929190918252602082015260400190565b60408051601f198184030181529082905261028591610bb4565b602060405180830381855afa1580156102a0573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906102c39190610bca565b6040518563ffffffff1660e01b81526004016102e29493929190610be1565b5f6040518083038186803b1580156102f8575f80fd5b505afa15801561030a573d5f803e3d5ffd5b5050505f84815260016020818152604092839020805460ff191690921790915590518581527fdd00992bb62ed043f2d437a844df0b524ab27e17bc67f8b8caf8bb5836be295992500160405180910390a1505050565b61037c848461037761037286866106b7565b610741565b610439565b50505050565b5f60607f7d75250e86556132c0e10c05b0f1d823ae72a5e277a596039576b6578cb252605f8080546103b390610c1f565b80601f01602080910402602001604051908101604052809291908181526020018280546103df90610c1f565b801561042a5780601f106104015761010080835404028352916020019161042a565b820191905f5260205f20905b81548152906001019060200180831161040d57829003601f168201915b50505050509050915091509091565b604080518082019091526060808252602082015261045a60045f8587610c57565b61046391610c7e565b6001600160e01b0319167fbfca9ccb000000000000000000000000000000000000000000000000000000006001600160e01b03191614610506576104aa60045f8587610c57565b6104b391610c7e565b604051632e2ce35360e21b81526001600160e01b031991821660048201527fbfca9ccb00000000000000000000000000000000000000000000000000000000909116602482015260440160405180910390fd5b600483111561052c5761051c8360048187610c57565b8101906105299190610d90565b90505b5f61053a825f0151846108a1565b60208301515190915015610682577f000000000000000000000000925d8331ddc0a1f0d96e68cf073dfe1d92b691876001600160a01b031663ab750e7583602001517f7d75250e86556132c0e10c05b0f1d823ae72a5e277a596039576b6578cb2526060027f7d75250e86556132c0e10c05b0f1d823ae72a5e277a596039576b6578cb25260866040516020016105db929190918252602082015260400190565b60408051601f19818403018152908290526105f591610bb4565b602060405180830381855afa158015610610573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906106339190610bca565b6040518463ffffffff1660e01b815260040161065193929190610e99565b5f6040518083038186803b158015610667575f80fd5b505afa158015610679573d5f803e3d5ffd5b505050506106b0565b5f8181526001602052604090205460ff166106b05760405163439cc0cd60e01b815260040160405180910390fd5b5050505050565b6106bf6109a7565b6040805160a0810182528481527fa3acc27117418996340b84e5a90f3ef4c49d22c79e44aad822ec9c313e1eb8e26020820152815180830183529091820190805f81526020015f60ff1681525081526020015f801b815260200161073860405180604001604052808681526020015f801b8152506108e3565b90529392505050565b5f60028060405161076a907172697363302e52656365697074436c61696d60701b815260120190565b602060405180830381855afa158015610785573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906107a89190610bca565b606084015184516020860151608087015160408801515160189060028111156107d3576107d3610ebd565b60408a810151602090810151825191820199909952908101969096526060860194909452608085019290925260a084015263ffffffff909116901b60e01b6001600160e01b03191660c082015260f89190911b6001600160f81b03191660c4820152600160fa1b60c882015260ca015b60408051601f198184030181529082905261085d91610bb4565b602060405180830381855afa158015610878573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061089b9190610bca565b92915050565b5f81815b84518110156108db576108d1828683815181106108c4576108c4610ed1565b6020026020010151610978565b91506001016108a5565b509392505050565b5f600280604051610906906b1c9a5cd8cc0b93dd5d1c1d5d60a21b8152600c0190565b602060405180830381855afa158015610921573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906109449190610bca565b83516020808601516040805192830194909452928101919091526060810191909152600160f91b6080820152608201610843565b5f818310610992575f8281526020849052604090206109a0565b5f8381526020839052604090205b9392505050565b6040805160a0810182525f80825260208201529081016109d6604080518082019091525f808252602082015290565b81525f6020820181905260409091015290565b5f602082840312156109f9575f80fd5b813567ffffffffffffffff811115610a0f575f80fd5b8201604081850312156109a0575f80fd5b5f60208284031215610a30575f80fd5b5035919050565b5f8083601f840112610a47575f80fd5b50813567ffffffffffffffff811115610a5e575f80fd5b602083019150836020828501011115610a75575f80fd5b9250929050565b5f805f60408486031215610a8e575f80fd5b83359250602084013567ffffffffffffffff811115610aab575f80fd5b610ab786828701610a37565b9497909650939450505050565b5f805f8060608587031215610ad7575f80fd5b843567ffffffffffffffff811115610aed575f80fd5b610af987828801610a37565b90989097506020870135966040013595509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b828152604060208201525f610b576040830184610b11565b949350505050565b602081525f6109a06020830184610b11565b5f808335601e19843603018112610b86575f80fd5b83018035915067ffffffffffffffff821115610ba0575f80fd5b602001915036819003821315610a75575f80fd5b5f82518060208501845e5f920191825250919050565b5f60208284031215610bda575f80fd5b5051919050565b60608152836060820152838560808301375f608085830101525f6080601f19601f870116830101905083602083015282604083015295945050505050565b600181811c90821680610c3357607f821691505b602082108103610c5157634e487b7160e01b5f52602260045260245ffd5b50919050565b5f8085851115610c65575f80fd5b83861115610c71575f80fd5b5050820193919092039150565b80356001600160e01b03198116906004841015610caf576001600160e01b0319600485900360031b81901b82161691505b5092915050565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715610ced57610ced610cb6565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610d1c57610d1c610cb6565b604052919050565b5f82601f830112610d33575f80fd5b813567ffffffffffffffff811115610d4d57610d4d610cb6565b610d60601f8201601f1916602001610cf3565b818152846020838601011115610d74575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215610da0575f80fd5b813567ffffffffffffffff811115610db6575f80fd5b820160408185031215610dc7575f80fd5b610dcf610cca565b813567ffffffffffffffff811115610de5575f80fd5b8201601f81018613610df5575f80fd5b803567ffffffffffffffff811115610e0f57610e0f610cb6565b8060051b610e1f60208201610cf3565b91825260208184018101929081019089841115610e3a575f80fd5b6020850194505b83851015610e6057843580835260209586019590935090910190610e41565b855250505050602082013567ffffffffffffffff811115610e7f575f80fd5b610e8b86828501610d24565b602083015250949350505050565b606081525f610eab6060830186610b11565b60208301949094525060400152919050565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52603260045260245ffdfea26469706673582212205976d1ea50c2019a9a6740f3140f728d189b9264d24c00ffcf2446abd4695b2264736f6c634300081a0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000925d8331ddc0a1f0d96e68cf073dfe1d92b691877d75250e86556132c0e10c05b0f1d823ae72a5e277a596039576b6578cb252600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005068747470733a2f2f676174657761792e70696e6174612e636c6f75642f697066732f516d5856763846457278687a78516953455944717744413562574c753777456e375a576346766a417366714a645700000000000000000000000000000000

-----Decoded View---------------
Arg [0] : verifier (address): 0x925d8331ddc0a1F0d96E68CF073DFE1d92b69187
Arg [1] : imageId (bytes32): 0x7d75250e86556132c0e10c05b0f1d823ae72a5e277a596039576b6578cb25260
Arg [2] : _imageUrl (string): https://gateway.pinata.cloud/ipfs/QmXVv8FErxhzxQiSEYDqwDA5bWLu7wEn7ZWcFvjAsfqJdW

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000925d8331ddc0a1f0d96e68cf073dfe1d92b69187
Arg [1] : 7d75250e86556132c0e10c05b0f1d823ae72a5e277a596039576b6578cb25260
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000050
Arg [4] : 68747470733a2f2f676174657761792e70696e6174612e636c6f75642f697066
Arg [5] : 732f516d5856763846457278687a78516953455944717744413562574c753777
Arg [6] : 456e375a576346766a417366714a645700000000000000000000000000000000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.