ETH Price: $3,476.01 (-1.19%)
Gas: 3 Gwei

Contract

0x031b216FaBec82310FEa3426b33455609b99AfC1
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Create Merkle Pr...177438402023-07-21 20:15:47367 days ago1689970547IN
Sudoswap : Property Checker Factory
0 ETH0.0031390342.4526184
Create Merkle Pr...177438052023-07-21 20:08:47367 days ago1689970127IN
Sudoswap : Property Checker Factory
0 ETH0.0030146240.77009058
Create Merkle Pr...177434942023-07-21 19:06:23367 days ago1689966383IN
Sudoswap : Property Checker Factory
0 ETH0.0052131570.50335925
Create Merkle Pr...177367532023-07-20 20:26:35368 days ago1689884795IN
Sudoswap : Property Checker Factory
0 ETH0.0025016333.83233403
Create Merkle Pr...176355672023-07-06 15:02:59382 days ago1688655779IN
Sudoswap : Property Checker Factory
0 ETH0.0038850252.54154113
Create Merkle Pr...176350812023-07-06 13:24:11382 days ago1688649851IN
Sudoswap : Property Checker Factory
0 ETH0.002292231
Create Merkle Pr...174596602023-06-11 21:54:23407 days ago1686520463IN
Sudoswap : Property Checker Factory
0 ETH0.0011515615.57391376
Create Merkle Pr...174560742023-06-11 9:46:35407 days ago1686476795IN
Sudoswap : Property Checker Factory
0 ETH0.0011867616.04990579

Latest 9 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
177438402023-07-21 20:15:47367 days ago1689970547
Sudoswap : Property Checker Factory
 Contract Creation0 ETH
177438052023-07-21 20:08:47367 days ago1689970127
Sudoswap : Property Checker Factory
 Contract Creation0 ETH
177434942023-07-21 19:06:23367 days ago1689966383
Sudoswap : Property Checker Factory
 Contract Creation0 ETH
177367532023-07-20 20:26:35368 days ago1689884795
Sudoswap : Property Checker Factory
 Contract Creation0 ETH
176355672023-07-06 15:02:59382 days ago1688655779
Sudoswap : Property Checker Factory
 Contract Creation0 ETH
176350812023-07-06 13:24:11382 days ago1688649851
Sudoswap : Property Checker Factory
 Contract Creation0 ETH
174596602023-06-11 21:54:23407 days ago1686520463
Sudoswap : Property Checker Factory
 Contract Creation0 ETH
174560742023-06-11 9:46:35407 days ago1686476795
Sudoswap : Property Checker Factory
 Contract Creation0 ETH
173093132023-05-21 17:46:59428 days ago1684691219  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PropertyCheckerFactory

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion
File 1 of 7 : PropertyCheckerFactory.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;

import {ClonesWithImmutableArgs} from "clones-with-immutable-args/ClonesWithImmutableArgs.sol";
import {MerklePropertyChecker} from "./MerklePropertyChecker.sol";
import {RangePropertyChecker} from "./RangePropertyChecker.sol";

contract PropertyCheckerFactory {
    using ClonesWithImmutableArgs for address;

    event NewMerklePropertyChecker(address indexed a, bytes32 indexed root);
    event NewRangePropertyChecker(address indexed a, uint256 indexed startInclusive, uint256 indexed endInclusive);

    MerklePropertyChecker immutable merklePropertyCheckerImplementation;
    RangePropertyChecker immutable rangePropertyCheckerImplementation;

    constructor(
        MerklePropertyChecker _merklePropertyCheckerImplementation,
        RangePropertyChecker _rangePropertyCheckerImplementation
    ) {
        merklePropertyCheckerImplementation = _merklePropertyCheckerImplementation;
        rangePropertyCheckerImplementation = _rangePropertyCheckerImplementation;
    }

    function createMerklePropertyChecker(bytes32 root) public returns (MerklePropertyChecker) {
        bytes memory data = abi.encodePacked(root);
        MerklePropertyChecker checker = MerklePropertyChecker(address(merklePropertyCheckerImplementation).clone(data));
        emit NewMerklePropertyChecker(address(checker), root);
        return checker;
    }

    function createRangePropertyChecker(uint256 startInclusive, uint256 endInclusive)
        public
        returns (RangePropertyChecker)
    {
        bytes memory data = abi.encodePacked(startInclusive, endInclusive);
        RangePropertyChecker checker = RangePropertyChecker(address(rangePropertyCheckerImplementation).clone(data));
        emit NewRangePropertyChecker(address(checker), startInclusive, endInclusive);
        return checker;
    }
}

File 2 of 7 : ClonesWithImmutableArgs.sol
// SPDX-License-Identifier: BSD

pragma solidity ^0.8.4;

/// @title ClonesWithImmutableArgs
/// @author wighawag, zefram.eth
/// @notice Enables creating clone contracts with immutable args
library ClonesWithImmutableArgs {
    error CreateFail();

    /// @notice Creates a clone proxy of the implementation contract, with immutable args
    /// @dev data cannot exceed 65535 bytes, since 2 bytes are used to store the data length
    /// @param implementation The implementation contract to clone
    /// @param data Encoded immutable args
    /// @return instance The address of the created clone
    function clone(address implementation, bytes memory data)
        internal
        returns (address payable instance)
    {
        // unrealistic for memory ptr or data length to exceed 256 bits
        unchecked {
            uint256 extraLength = data.length + 2; // +2 bytes for telling how much data there is appended to the call
            uint256 creationSize = 0x41 + extraLength;
            uint256 runSize = creationSize - 10;
            uint256 dataPtr;
            uint256 ptr;
            // solhint-disable-next-line no-inline-assembly
            assembly {
                ptr := mload(0x40)

                // -------------------------------------------------------------------------------------------------------------
                // CREATION (10 bytes)
                // -------------------------------------------------------------------------------------------------------------

                // 61 runtime  | PUSH2 runtime (r)     | r                       | –
                mstore(
                    ptr,
                    0x6100000000000000000000000000000000000000000000000000000000000000
                )
                mstore(add(ptr, 0x01), shl(240, runSize)) // size of the contract running bytecode (16 bits)

                // creation size = 0a
                // 3d          | RETURNDATASIZE        | 0 r                     | –
                // 81          | DUP2                  | r 0 r                   | –
                // 60 creation | PUSH1 creation (c)    | c r 0 r                 | –
                // 3d          | RETURNDATASIZE        | 0 c r 0 r               | –
                // 39          | CODECOPY              | 0 r                     | [0-runSize): runtime code
                // f3          | RETURN                |                         | [0-runSize): runtime code

                // -------------------------------------------------------------------------------------------------------------
                // RUNTIME (55 bytes + extraLength)
                // -------------------------------------------------------------------------------------------------------------

                // 3d          | RETURNDATASIZE        | 0                       | –
                // 3d          | RETURNDATASIZE        | 0 0                     | –
                // 3d          | RETURNDATASIZE        | 0 0 0                   | –
                // 3d          | RETURNDATASIZE        | 0 0 0 0                 | –
                // 36          | CALLDATASIZE          | cds 0 0 0 0             | –
                // 3d          | RETURNDATASIZE        | 0 cds 0 0 0 0           | –
                // 3d          | RETURNDATASIZE        | 0 0 cds 0 0 0 0         | –
                // 37          | CALLDATACOPY          | 0 0 0 0                 | [0, cds) = calldata
                // 61          | PUSH2 extra           | extra 0 0 0 0           | [0, cds) = calldata
                mstore(
                    add(ptr, 0x03),
                    0x3d81600a3d39f33d3d3d3d363d3d376100000000000000000000000000000000
                )
                mstore(add(ptr, 0x13), shl(240, extraLength))

                // 60 0x37     | PUSH1 0x37            | 0x37 extra 0 0 0 0      | [0, cds) = calldata // 0x37 (55) is runtime size - data
                // 36          | CALLDATASIZE          | cds 0x37 extra 0 0 0 0  | [0, cds) = calldata
                // 39          | CODECOPY              | 0 0 0 0                 | [0, cds) = calldata, [cds, cds+0x37) = extraData
                // 36          | CALLDATASIZE          | cds 0 0 0 0             | [0, cds) = calldata, [cds, cds+0x37) = extraData
                // 61 extra    | PUSH2 extra           | extra cds 0 0 0 0       | [0, cds) = calldata, [cds, cds+0x37) = extraData
                mstore(
                    add(ptr, 0x15),
                    0x6037363936610000000000000000000000000000000000000000000000000000
                )
                mstore(add(ptr, 0x1b), shl(240, extraLength))

                // 01          | ADD                   | cds+extra 0 0 0 0       | [0, cds) = calldata, [cds, cds+0x37) = extraData
                // 3d          | RETURNDATASIZE        | 0 cds 0 0 0 0           | [0, cds) = calldata, [cds, cds+0x37) = extraData
                // 73 addr     | PUSH20 0x123…         | addr 0 cds 0 0 0 0      | [0, cds) = calldata, [cds, cds+0x37) = extraData
                mstore(
                    add(ptr, 0x1d),
                    0x013d730000000000000000000000000000000000000000000000000000000000
                )
                mstore(add(ptr, 0x20), shl(0x60, implementation))

                // 5a          | GAS                   | gas addr 0 cds 0 0 0 0  | [0, cds) = calldata, [cds, cds+0x37) = extraData
                // f4          | DELEGATECALL          | success 0 0             | [0, cds) = calldata, [cds, cds+0x37) = extraData
                // 3d          | RETURNDATASIZE        | rds success 0 0         | [0, cds) = calldata, [cds, cds+0x37) = extraData
                // 3d          | RETURNDATASIZE        | rds rds success 0 0     | [0, cds) = calldata, [cds, cds+0x37) = extraData
                // 93          | SWAP4                 | 0 rds success 0 rds     | [0, cds) = calldata, [cds, cds+0x37) = extraData
                // 80          | DUP1                  | 0 0 rds success 0 rds   | [0, cds) = calldata, [cds, cds+0x37) = extraData
                // 3e          | RETURNDATACOPY        | success 0 rds           | [0, rds) = return data (there might be some irrelevant leftovers in memory [rds, cds+0x37) when rds < cds+0x37)
                // 60 0x35     | PUSH1 0x35            | 0x35 sucess 0 rds       | [0, rds) = return data
                // 57          | JUMPI                 | 0 rds                   | [0, rds) = return data
                // fd          | REVERT                | –                       | [0, rds) = return data
                // 5b          | JUMPDEST              | 0 rds                   | [0, rds) = return data
                // f3          | RETURN                | –                       | [0, rds) = return data
                mstore(
                    add(ptr, 0x34),
                    0x5af43d3d93803e603557fd5bf300000000000000000000000000000000000000
                )
            }

            // -------------------------------------------------------------------------------------------------------------
            // APPENDED DATA (Accessible from extcodecopy)
            // (but also send as appended data to the delegatecall)
            // -------------------------------------------------------------------------------------------------------------

            extraLength -= 2;
            uint256 counter = extraLength;
            uint256 copyPtr = ptr + 0x41;
            // solhint-disable-next-line no-inline-assembly
            assembly {
                dataPtr := add(data, 32)
            }
            for (; counter >= 32; counter -= 32) {
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    mstore(copyPtr, mload(dataPtr))
                }

                copyPtr += 32;
                dataPtr += 32;
            }
            uint256 mask = ~(256**(32 - counter) - 1);
            // solhint-disable-next-line no-inline-assembly
            assembly {
                mstore(copyPtr, and(mload(dataPtr), mask))
            }
            copyPtr += counter;
            // solhint-disable-next-line no-inline-assembly
            assembly {
                mstore(copyPtr, shl(240, extraLength))
            }
            // solhint-disable-next-line no-inline-assembly
            assembly {
                instance := create(0, ptr, creationSize)
            }
            if (instance == address(0)) {
                revert CreateFail();
            }
        }
    }
}

File 3 of 7 : MerklePropertyChecker.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;

import {IPropertyChecker} from "./IPropertyChecker.sol";
import {Clone} from "clones-with-immutable-args/Clone.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";

contract MerklePropertyChecker is IPropertyChecker, Clone {
    error MerklePropertyChecker__InputMismatch();
    // Immutable params

    /**
     * @return Returns the merkle root
     */
    function getMerkleRoot() public pure returns (bytes32) {
        return bytes32(_getArgUint256(0));
    }

    function hasProperties(uint256[] calldata ids, bytes calldata params) external pure returns (bool isAllowed) {
        isAllowed = true;
        bytes32 root = getMerkleRoot();
        (bytes[] memory proofList) = abi.decode(params, (bytes[]));

        uint256 numIds = ids.length;
        if (numIds != proofList.length) revert MerklePropertyChecker__InputMismatch();

        for (uint256 i; i < numIds;) {
            bytes32[] memory proof = abi.decode(proofList[i], (bytes32[]));
            if (!MerkleProof.verify(proof, root, keccak256(abi.encodePacked(ids[i])))) {
                return false;
            }

            unchecked {
                ++i;
            }
        }
    }
}

File 4 of 7 : RangePropertyChecker.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;

import {IPropertyChecker} from "./IPropertyChecker.sol";
import {Clone} from "clones-with-immutable-args/Clone.sol";

contract RangePropertyChecker is IPropertyChecker, Clone {
    // Immutable params

    /**
     * @return Returns the lower bound of IDs allowed
     */
    function getLowerBoundInclusive() public pure returns (uint256) {
        return _getArgUint256(0);
    }

    /**
     * @return Returns the upper bound of IDs allowed
     */
    function getUpperBoundInclusive() public pure returns (uint256) {
        return _getArgUint256(32);
    }

    function hasProperties(uint256[] calldata ids, bytes calldata) external pure returns (bool isAllowed) {
        isAllowed = true;
        uint256 lowerBound = getLowerBoundInclusive();
        uint256 upperBound = getUpperBoundInclusive();
        uint256 numIds = ids.length;
        for (uint256 i; i < numIds;) {
            if (ids[i] < lowerBound) {
                return false;
            } else if (ids[i] > upperBound) {
                return false;
            }

            unchecked {
                ++i;
            }
        }
    }
}

File 5 of 7 : IPropertyChecker.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;

interface IPropertyChecker {
    function hasProperties(uint256[] calldata ids, bytes calldata params) external returns (bool);
}

File 6 of 7 : Clone.sol
// SPDX-License-Identifier: BSD
pragma solidity ^0.8.4;

/// @title Clone
/// @author zefram.eth
/// @notice Provides helper functions for reading immutable args from calldata
contract Clone {
    /// @notice Reads an immutable arg with type address
    /// @param argOffset The offset of the arg in the packed data
    /// @return arg The arg value
    function _getArgAddress(uint256 argOffset)
        internal
        pure
        returns (address arg)
    {
        uint256 offset = _getImmutableArgsOffset();
        // solhint-disable-next-line no-inline-assembly
        assembly {
            arg := shr(0x60, calldataload(add(offset, argOffset)))
        }
    }

    /// @notice Reads an immutable arg with type uint256
    /// @param argOffset The offset of the arg in the packed data
    /// @return arg The arg value
    function _getArgUint256(uint256 argOffset)
        internal
        pure
        returns (uint256 arg)
    {
        uint256 offset = _getImmutableArgsOffset();
        // solhint-disable-next-line no-inline-assembly
        assembly {
            arg := calldataload(add(offset, argOffset))
        }
    }

    /// @notice Reads a uint256 array stored in the immutable args.
    /// @param argOffset The offset of the arg in the packed data
    /// @param arrLen Number of elements in the array
    /// @return arr The array
    function _getArgUint256Array(uint256 argOffset, uint64 arrLen)
        internal
        pure
      returns (uint256[] memory arr)
    {
      uint256 offset = _getImmutableArgsOffset();
      uint256 el;
      arr = new uint256[](arrLen);
      for (uint64 i = 0; i < arrLen; i++) {
        assembly {
          // solhint-disable-next-line no-inline-assembly
          el := calldataload(add(add(offset, argOffset), mul(i, 32)))
        }
        arr[i] = el;
      }
      return arr;
    }

    /// @notice Reads an immutable arg with type uint64
    /// @param argOffset The offset of the arg in the packed data
    /// @return arg The arg value
    function _getArgUint64(uint256 argOffset)
        internal
        pure
        returns (uint64 arg)
    {
        uint256 offset = _getImmutableArgsOffset();
        // solhint-disable-next-line no-inline-assembly
        assembly {
            arg := shr(0xc0, calldataload(add(offset, argOffset)))
        }
    }

    /// @notice Reads an immutable arg with type uint8
    /// @param argOffset The offset of the arg in the packed data
    /// @return arg The arg value
    function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) {
        uint256 offset = _getImmutableArgsOffset();
        // solhint-disable-next-line no-inline-assembly
        assembly {
            arg := shr(0xf8, calldataload(add(offset, argOffset)))
        }
    }

    /// @return offset The offset of the packed immutable args in calldata
    function _getImmutableArgsOffset() internal pure returns (uint256 offset) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            offset := sub(
                calldatasize(),
                add(shr(240, calldataload(sub(calldatasize(), 2))), 2)
            )
        }
    }
}

File 7 of 7 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @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 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}
     *
     * _Available since v4.7._
     */
    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.
     *
     * _Available since v4.4._
     */
    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}
     *
     * _Available since v4.7._
     */
    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.
     *
     * _Available since v4.7._
     */
    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.
     *
     * _Available since v4.7._
     */
    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).
     *
     * _Available since v4.7._
     */
    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 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // 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) {
            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.
     *
     * _Available since v4.7._
     */
    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 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // 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) {
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    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)
        }
    }
}

Settings
{
  "remappings": [
    "@manifoldxyz/=lib/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@prb/math/=lib/prb-math/src/",
    "clones-with-immutable-args/=lib/clones-with-immutable-args/src/",
    "create3-factory/=lib/create3-factory/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "libraries-solidity/=lib/libraries-solidity/contracts/",
    "manifoldxyz/=lib/royalty-registry-solidity/contracts/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "royalty-registry-solidity/=lib/royalty-registry-solidity/contracts/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "metadata": {
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract MerklePropertyChecker","name":"_merklePropertyCheckerImplementation","type":"address"},{"internalType":"contract RangePropertyChecker","name":"_rangePropertyCheckerImplementation","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CreateFail","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"a","type":"address"},{"indexed":true,"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"NewMerklePropertyChecker","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"a","type":"address"},{"indexed":true,"internalType":"uint256","name":"startInclusive","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endInclusive","type":"uint256"}],"name":"NewRangePropertyChecker","type":"event"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"createMerklePropertyChecker","outputs":[{"internalType":"contract MerklePropertyChecker","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startInclusive","type":"uint256"},{"internalType":"uint256","name":"endInclusive","type":"uint256"}],"name":"createRangePropertyChecker","outputs":[{"internalType":"contract RangePropertyChecker","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"}]

60c060405234801561001057600080fd5b5060405161054a38038061054a83398101604081905261002f9161005e565b6001600160a01b039182166080521660a052610098565b6001600160a01b038116811461005b57600080fd5b50565b6000806040838503121561007157600080fd5b825161007c81610046565b602084015190925061008d81610046565b809150509250929050565b60805160a05161048e6100bc600039600060f5015260006101cc015261048e6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635912f4041461003b578063d43554f814610077575b600080fd5b61004e61004936600461041d565b61008a565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61004e61008536600461043f565b61016a565b60008083836040516020016100a9929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600061011b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168361023f565b905083858273ffffffffffffffffffffffffffffffffffffffff167f0c5e6e787c28ecd0a0410f3aea9d9fba678ad9123788642aa29d80487ad5cc2960405160405180910390a4949350505050565b6000808260405160200161018091815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060006101f273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168361023f565b9050838173ffffffffffffffffffffffffffffffffffffffff167fabaddb61b4494cd820b234e010babe4d23ee8dd24b02d5f286410a05533ee64d60405160405180910390a39392505050565b80516040517f610000000000000000000000000000000000000000000000000000000000000081526039820160f081811b60018401527f3d81600a3d39f33d3d3d3d363d3d376100000000000000000000000000000000600384015260028401901b601383018190527f60373639366100000000000000000000000000000000000000000000000000006015840152601b8301527f013d730000000000000000000000000000000000000000000000000000000000601d830152606085901b6020808401919091527f5af43d3d93803e603557fd5bf30000000000000000000000000000000000000060348401526000939260438401929186019084604182015b6020821061037d57835181526020938401937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019101610340565b83517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208490036101000a0119908116825260f088901b91830191825286846000f0985073ffffffffffffffffffffffffffffffffffffffff891661040f576040517febfef18800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505092915050565b6000806040838503121561043057600080fd5b50508035926020909101359150565b60006020828403121561045157600080fd5b503591905056fea2646970667358221220271c061b767eb97b9557cf1d34354b61ca8b698b843e1c8016282a4d4e69937264736f6c634300081400330000000000000000000000005a9582b667c0f8c61ac2a2d856ec0fbf27a632460000000000000000000000000374352456bf2ccfd919ac9f9a53e971daadc9b5

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635912f4041461003b578063d43554f814610077575b600080fd5b61004e61004936600461041d565b61008a565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61004e61008536600461043f565b61016a565b60008083836040516020016100a9929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600061011b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000374352456bf2ccfd919ac9f9a53e971daadc9b5168361023f565b905083858273ffffffffffffffffffffffffffffffffffffffff167f0c5e6e787c28ecd0a0410f3aea9d9fba678ad9123788642aa29d80487ad5cc2960405160405180910390a4949350505050565b6000808260405160200161018091815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060006101f273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005a9582b667c0f8c61ac2a2d856ec0fbf27a63246168361023f565b9050838173ffffffffffffffffffffffffffffffffffffffff167fabaddb61b4494cd820b234e010babe4d23ee8dd24b02d5f286410a05533ee64d60405160405180910390a39392505050565b80516040517f610000000000000000000000000000000000000000000000000000000000000081526039820160f081811b60018401527f3d81600a3d39f33d3d3d3d363d3d376100000000000000000000000000000000600384015260028401901b601383018190527f60373639366100000000000000000000000000000000000000000000000000006015840152601b8301527f013d730000000000000000000000000000000000000000000000000000000000601d830152606085901b6020808401919091527f5af43d3d93803e603557fd5bf30000000000000000000000000000000000000060348401526000939260438401929186019084604182015b6020821061037d57835181526020938401937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019101610340565b83517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208490036101000a0119908116825260f088901b91830191825286846000f0985073ffffffffffffffffffffffffffffffffffffffff891661040f576040517febfef18800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505092915050565b6000806040838503121561043057600080fd5b50508035926020909101359150565b60006020828403121561045157600080fd5b503591905056fea2646970667358221220271c061b767eb97b9557cf1d34354b61ca8b698b843e1c8016282a4d4e69937264736f6c63430008140033

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

0000000000000000000000005a9582b667c0f8c61ac2a2d856ec0fbf27a632460000000000000000000000000374352456bf2ccfd919ac9f9a53e971daadc9b5

-----Decoded View---------------
Arg [0] : _merklePropertyCheckerImplementation (address): 0x5A9582B667C0F8c61Ac2A2d856ec0fBf27a63246
Arg [1] : _rangePropertyCheckerImplementation (address): 0x0374352456bf2CCFD919Ac9f9a53e971DaADC9B5

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000005a9582b667c0f8c61ac2a2d856ec0fbf27a63246
Arg [1] : 0000000000000000000000000374352456bf2ccfd919ac9f9a53e971daadc9b5


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ 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.