ETH Price: $2,972.82 (-1.57%)
Gas: 2 Gwei

Contract

0xAA0e012d35Cf7d6EcB6c2Bf861e71248501D3226
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value

There are no matching entries

Please try again later

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
202491212024-07-06 18:00:1121 hrs ago1720288811
0xAA0e012d...8501D3226
0 ETH
202491212024-07-06 18:00:1121 hrs ago1720288811
0xAA0e012d...8501D3226
0 ETH
202488012024-07-06 16:55:5922 hrs ago1720284959
0xAA0e012d...8501D3226
0 ETH
202488012024-07-06 16:55:5922 hrs ago1720284959
0xAA0e012d...8501D3226
0 ETH
202449802024-07-06 4:07:1135 hrs ago1720238831
0xAA0e012d...8501D3226
0 ETH
202449802024-07-06 4:07:1135 hrs ago1720238831
0xAA0e012d...8501D3226
0 ETH
202448432024-07-06 3:39:4736 hrs ago1720237187
0xAA0e012d...8501D3226
0 ETH
202448432024-07-06 3:39:4736 hrs ago1720237187
0xAA0e012d...8501D3226
0 ETH
202443892024-07-06 2:08:3537 hrs ago1720231715
0xAA0e012d...8501D3226
0 ETH
202443892024-07-06 2:08:3537 hrs ago1720231715
0xAA0e012d...8501D3226
0 ETH
202294982024-07-04 0:14:233 days ago1720052063
0xAA0e012d...8501D3226
0 ETH
202294982024-07-04 0:14:233 days ago1720052063
0xAA0e012d...8501D3226
0 ETH
202280362024-07-03 19:20:473 days ago1720034447
0xAA0e012d...8501D3226
0 ETH
202280362024-07-03 19:20:473 days ago1720034447
0xAA0e012d...8501D3226
0 ETH
202266162024-07-03 14:35:474 days ago1720017347
0xAA0e012d...8501D3226
0 ETH
202266162024-07-03 14:35:474 days ago1720017347
0xAA0e012d...8501D3226
0 ETH
202227952024-07-03 1:46:474 days ago1719971207
0xAA0e012d...8501D3226
0 ETH
202227952024-07-03 1:46:474 days ago1719971207
0xAA0e012d...8501D3226
0 ETH
202161022024-07-02 3:18:595 days ago1719890339
0xAA0e012d...8501D3226
0 ETH
202161022024-07-02 3:18:595 days ago1719890339
0xAA0e012d...8501D3226
0 ETH
202147312024-07-01 22:43:115 days ago1719873791
0xAA0e012d...8501D3226
0 ETH
202147312024-07-01 22:43:115 days ago1719873791
0xAA0e012d...8501D3226
0 ETH
202140072024-07-01 20:18:115 days ago1719865091
0xAA0e012d...8501D3226
0 ETH
202140072024-07-01 20:18:115 days ago1719865091
0xAA0e012d...8501D3226
0 ETH
202101612024-07-01 7:25:116 days ago1719818711
0xAA0e012d...8501D3226
0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SignedZone

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 8 : SignedZone.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {
    ZoneParameters,
    Schema,
    ReceivedItem
} from "../lib/ConsiderationStructs.sol";

import { ZoneInterface } from "../interfaces/ZoneInterface.sol";

import {
    SignedZoneEventsAndErrors
} from "./interfaces/SignedZoneEventsAndErrors.sol";

import { SIP5Interface } from "./interfaces/SIP5Interface.sol";

import {
    SignedZoneControllerInterface
} from "./interfaces/SignedZoneControllerInterface.sol";

import "./lib/SignedZoneConstants.sol";

/**
 * @title  SignedZone
 * @author ryanio, BCLeFevre
 * @custom:modifiedby Tony Snark
 * @notice SignedZone is an implementation of SIP-7 that requires orders
 *         to be signed by an approved signer.
 *         https://github.com/ProjectOpenSea/SIPs/blob/main/SIPS/sip-7.md
 *
 *         Modification:
 *         Removes support for SIP7 sub-standard 1.
 *         Adds support for SIP7 sub-standard 3.
 */
contract SignedZone is SignedZoneEventsAndErrors, ZoneInterface, SIP5Interface {
    /// @dev The zone's controller that is set during deployment.
    address private immutable _controller;

    /// @dev The authorized signers, and if they are active
    mapping(address => bool) private _signers;

    /// @dev The EIP-712 digest parameters.
    bytes32 internal immutable _NAME_HASH = keccak256(bytes("SignedZone"));
    bytes32 internal immutable _VERSION_HASH = keccak256(bytes("1.0.0"));
    // prettier-ignore
    bytes32 internal immutable _EIP_712_DOMAIN_TYPEHASH = keccak256(
          abi.encodePacked(
            "EIP712Domain(",
                "string name,",
                "string version,",
                "uint256 chainId,",
                "address verifyingContract",
            ")"
          )
        );
    // prettier-ignore
    bytes32 internal immutable _SIGNED_ORDER_TYPEHASH = keccak256(
          abi.encodePacked(
            "SignedOrder(",
                "address fulfiller,",
                "uint64 expiration,",
                "bytes32 orderHash,",
                "bytes context",
            ")"
          )
        );

    bytes public constant CONSIDERATION_BYTES =
        // prettier-ignore
        abi.encodePacked(
              "Consideration(",
                  "ReceivedItem[] consideration",
              ")"
        );

    bytes public constant RECEIVED_ITEM_BYTES =
        // prettier-ignore
        abi.encodePacked(
              "ReceivedItem(",
                  "uint8 itemType,",
                  "address token,",
                  "uint256 identifier,",
                  "uint256 amount,",
                  "address recipient",
              ")"
        );

    bytes32 public constant RECEIVED_ITEM_HASHTYPE =
        keccak256(RECEIVED_ITEM_BYTES);

    bytes32 public constant CONSIDERATION_HASHTYPE =
        keccak256(abi.encodePacked(CONSIDERATION_BYTES, RECEIVED_ITEM_BYTES));

    uint256 internal immutable _CHAIN_ID = block.chainid;
    bytes32 internal immutable _DOMAIN_SEPARATOR;

    /**
     * @notice Constructor to deploy the contract.
     */
    constructor() {
        // Set the deployer as the controller.
        _controller = msg.sender;

        // Derive and set the domain separator.
        _DOMAIN_SEPARATOR = _deriveDomainSeparator();

        // Emit an event to signal a SIP-5 contract has been deployed.
        emit SeaportCompatibleContractDeployed();
    }

    /**
     * @notice Check if a given order including extraData is currently valid.
     *
     * @dev This function is called by Seaport whenever any extraData is
     *      provided by the caller.
     *
     * @return validOrderMagicValue A magic value indicating if the order is
     *                              currently valid.
     */
    function validateOrder(ZoneParameters calldata zoneParameters)
        public
        view
        virtual
        override
        returns (bytes4 validOrderMagicValue)
    {
        // Check Zone parameters validity.
        _assertValidZoneParameters();

        // Put the extraData and orderHash on the stack for cheaper access.
        bytes calldata extraData = zoneParameters.extraData;
        bytes32 orderHash = zoneParameters.orderHash;
        uint256 considerationLength;
        // Declare a variable to hold the expiration.
        uint64 expiration;

        // Validate the extraData.
        assembly {
            // Get the length of the extraData.
            let extraDataPtr := add(0x24, calldataload(Zone_extraData_cdPtr))
            let extraDataLength := calldataload(extraDataPtr)

            if iszero(
                eq(extraDataLength, InvalidExtraDataLength_epected_length)
            ) {
                // Store left-padded selector with push4, mem[28:32] = selector
                mstore(0, InvalidExtraDataLength_error_selector)
                mstore(InvalidExtraDataLength_error_orderHash_ptr, orderHash)
                // revert(abi.encodeWithSignature(
                //   "InvalidExtraDataLength(bytes32)", orderHash)
                // )
                revert(0x1c, InvalidExtraDataLength_error_length)
            }

            // extraData bytes 0-1: SIP-6 version byte (MUST be 0x00)
            let versionByte := shr(248, calldataload(add(extraDataPtr, 0x20)))

            if iszero(eq(versionByte, 0x00)) {
                // Store left-padded selector with push4, mem[28:32] = selector
                mstore(0, InvalidSIP6Version_error_selector)
                mstore(InvalidSIP6Version_error_orderHash_ptr, orderHash)
                // revert(abi.encodeWithSignature(
                //   "InvalidSIP6Version(bytes32)", orderHash)
                // )
                revert(0x1c, InvalidSIP6Version_error_length)
            }

            // extraData bytes 93-94: Substandard #1 (MUST be 0x00)
            let subStandardVersionByte := shr(
                248,
                calldataload(
                    add(extraDataPtr, ExtraData_substandard_version_byte_offset)
                )
            )

            if iszero(eq(subStandardVersionByte, 0x00)) {
                // Store left-padded selector with push4, mem[28:32] = selector
                mstore(0, InvalidSubstandardVersion_error_selector)
                mstore(InvalidSubstandardVersion_error_orderHash_ptr, orderHash)
                // revert(abi.encodeWithSignature(
                //   "InvalidSubstandardVersion(bytes32)", orderHash)
                // )
                revert(0x1c, InvalidSubstandardVersion_error_length)
            }

            // extraData bytes 21-29: expiration timestamp (uint64)
            expiration := shr(
                192,
                calldataload(add(extraDataPtr, ExtraData_expiration_offset))
            )
            // Revert if expired.
            if lt(expiration, timestamp()) {
                // Store left-padded selector with push4, mem[28:32] = selector
                mstore(0, SignatureExpired_error_selector)
                mstore(SignatureExpired_error_expiration_ptr, expiration)
                mstore(SignatureExpired_error_orderHash_ptr, orderHash)
                // revert(abi.encodeWithSignature(
                //   "SignatureExpired(uint256, bytes32)", expiration orderHash)
                // )
                revert(0x1c, SignatureExpired_error_length)
            }

            // // Get the length of the consideration array.
            considerationLength := calldataload(
                add(0x24, calldataload(Zone_consideration_head_cdPtr))
            )
        }

        // extraData bytes 29-93: signature
        // (strictly requires 64 byte compact sig, EIP-2098)
        bytes calldata signature = extraData[29:93];

        // extraData bytes 93-end: context (optional, variable length)
        bytes calldata context = extraData[93:];

        // Check the validity of the Substandard #1 extraData and get the
        // expected fulfiller address.
        address expectedFulfiller = _getExpectedFulfiller(orderHash);

        // Check the validity of the Substandard #1 extraData and get the
        // expected fulfiller address.
        if (considerationLength > 0) {
            _assertValidSubstandard(
                _deriveConsiderationHash(zoneParameters.consideration),
                orderHash
            );
        }

        // Derive the signedOrder hash.
        bytes32 signedOrderHash = _deriveSignedOrderHash(
            expectedFulfiller,
            expiration,
            orderHash,
            context
        );

        // Derive the EIP-712 digest using the domain separator and signedOrder
        // hash.
        bytes32 digest = _deriveEIP712Digest(
            _domainSeparator(),
            signedOrderHash
        );

        // Recover the signer address from the digest and signature.
        address recoveredSigner = _recoverSigner(digest, signature);

        // Revert if the signer is not active.
        if (!_signers[recoveredSigner]) {
            revert SignerNotActive(recoveredSigner, orderHash);
        }
        // Return the selector of validateOrder as the magic value.
        validOrderMagicValue = ZoneInterface.validateOrder.selector;
    }

    /**
     * @dev Returns Seaport metadata for this contract, returning the
     *      contract name and supported schemas.
     *
     * @return name The contract name
     * @return schemas  The supported SIPs
     */
    function getSeaportMetadata()
        external
        view
        override(SIP5Interface, ZoneInterface)
        returns (string memory name, Schema[] memory schemas)
    {
        // Return the supported SIPs.
        schemas = new Schema[](1);
        schemas[0].id = 7;

        // Get the SIP-7 information.
        (
            bytes32 domainSeparator,
            string memory zoneName,
            string memory apiEndpoint,
            uint256[] memory substandards,
            string memory documentationURI
        ) = _sip7Information();

        // Return the zone name.
        name = zoneName;

        // Encode the SIP-7 information.
        schemas[0].metadata = abi.encode(
            domainSeparator,
            apiEndpoint,
            substandards,
            documentationURI
        );
    }

    /**
     * @notice The fallback function is used as a dispatcher for the
     *         `updateSigner`, `getActiveSigners` and `supportsInterface`
     *         functions.
     */
    // prettier-ignore
    fallback(bytes calldata) external payable returns (bytes memory output) {
        // Get the function selector.
        bytes4 selector = msg.sig;

        if (selector == 0xf460590b) {
            // updateSigner(address,bool)

            // Get the signer, and active status.
            address signer = abi.decode(msg.data[4:], (address));
            bool active = abi.decode(msg.data[36:], (bool));

            // Call to update the signer.
            _updateSigner(signer, active);
        } else if (selector == 0xa784b80c) {
            // getActiveSigners()

            // Call the internal function to get the active signers.
            return abi.encode(_getActiveSigners());
        } else if (selector == 0x01ffc9a7) {
            // supportsInterface(bytes4)

            // Get the interface ID.
            bytes4 interfaceId = abi.decode(msg.data[4:], (bytes4));

            // Call the internal function to determine if the interface is
            // supported.
            return abi.encode(_supportsInterface(interfaceId));
        }
    }

    /**
     * @notice Add or remove a signer to the zone.
     *         Only the controller can call this function.
     *
     * @param signer The signer address to add or remove.
     */
    function _updateSigner(address signer, bool active) internal {
        // Only the controller can call this function.
        _assertCallerIsController();
        // Add or remove the signer.
        active ? _addSigner(signer) : _removeSigner(signer);
    }

    /**
     * @notice Add a new signer to the zone.
     *         Only the controller or an active signer can call this function.
     *
     * @param signer The new signer address to add.
     */
    function _addSigner(address signer) internal {
        // Set the signer info.
        _signers[signer] = true;
        // Emit an event that the signer was added.
        emit SignerAdded(signer);
    }

    /**
     * @notice Remove an active signer from the zone.
     *         Only the controller or an active signer can call this function.
     *
     * @param signer The signer address to remove.
     */
    function _removeSigner(address signer) internal {
        // Set the signer's active status to false.
        _signers[signer] = false;

        // Emit an event that the signer was removed.
        emit SignerRemoved(signer);
    }

    /**
     * @notice Returns the active signers for the zone.
     *
     * @return signers The active signers.
     */
    function _getActiveSigners()
        internal
        view
        returns (address[] memory signers)
    {
        // Return the active signers for the zone by calling the controller.
        signers = SignedZoneControllerInterface(_controller).getActiveSigners(
            address(this)
        );
    }

    /**
     * @notice Returns whether the interface is supported.
     *
     * @param interfaceId The interface id to check against.
     */
    function _supportsInterface(bytes4 interfaceId)
        internal
        pure
        returns (bool supportsInterface)
    {
        // Determine if the interface is supported.
        supportsInterface =
            interfaceId == type(SIP5Interface).interfaceId || // SIP-5
            interfaceId == type(ZoneInterface).interfaceId || // ZoneInterface
            interfaceId == 0x01ffc9a7; // ERC-165
    }

    /**
     * @notice Internal call to return the signing information, substandards,
     *         and documentation about the zone.
     *
     * @return domainSeparator  The domain separator used for signing.
     * @return zoneName         The zone name.
     * @return apiEndpoint      The API endpoint for the zone.
     * @return substandards     The substandards supported by the zone.
     * @return documentationURI The documentation URI for the zone.
     */
    function _sip7Information()
        internal
        view
        returns (
            bytes32 domainSeparator,
            string memory zoneName,
            string memory apiEndpoint,
            uint256[] memory substandards,
            string memory documentationURI
        )
    {
        // Return the SIP-7 information.
        domainSeparator = _domainSeparator();

        // Get the SIP-7 information from the controller.
        (
            ,
            zoneName,
            apiEndpoint,
            substandards,
            documentationURI
        ) = SignedZoneControllerInterface(_controller)
            .getAdditionalZoneInformation(address(this));
    }

    /**
     * @dev Derive the signedOrder hash from the orderHash and expiration.
     *
     * @param fulfiller  The expected fulfiller address.
     * @param expiration The signature expiration timestamp.
     * @param orderHash  The order hash.
     * @param context    The optional variable-length context.
     *
     * @return signedOrderHash The signedOrder hash.
     *
     */
    function _deriveSignedOrderHash(
        address fulfiller,
        uint64 expiration,
        bytes32 orderHash,
        bytes calldata context
    ) internal view returns (bytes32 signedOrderHash) {
        // Derive the signed order hash.
        signedOrderHash = keccak256(
            abi.encode(
                _SIGNED_ORDER_TYPEHASH,
                fulfiller,
                expiration,
                orderHash,
                keccak256(context)
            )
        );
    }

    /**
     * @dev Internal view function to return the signer of a signature.
     *
     * @param digest    The digest to verify the signature against.
     * @param signature A signature from the signer indicating that the order
     *                  has been approved.
     *
     * @return recoveredSigner The recovered signer.
     */
    function _recoverSigner(bytes32 digest, bytes memory signature)
        internal
        view
        returns (address recoveredSigner)
    {
        // Utilize assembly to perform optimized signature verification check.
        assembly {
            // Ensure that first word of scratch space is empty.
            mstore(0, 0)

            // Declare value for v signature parameter.
            let v

            // Get the length of the signature.
            let signatureLength := mload(signature)

            // Get the pointer to the value preceding the signature length.
            // This will be used for temporary memory overrides - either the
            // signature head for isValidSignature or the digest for ecrecover.
            let wordBeforeSignaturePtr := sub(signature, OneWord)

            // Cache the current value behind the signature to restore it later.
            let cachedWordBeforeSignature := mload(wordBeforeSignaturePtr)

            // Declare lenDiff + recoveredSigner scope to manage stack pressure.
            {
                // Take the difference between the max ECDSA signature length
                // and the actual signature length. Overflow desired for any
                // values > 65. If the diff is not 0 or 1, it is not a valid
                // ECDSA signature - move on to EIP1271 check.
                let lenDiff := sub(ECDSA_MaxLength, signatureLength)

                // If diff is 0 or 1, it may be an ECDSA signature.
                // Try to recover signer.
                if iszero(gt(lenDiff, 1)) {
                    // Read the signature `s` value.
                    let originalSignatureS := mload(
                        add(signature, ECDSA_signature_s_offset)
                    )

                    // Read the first byte of the word after `s`. If the
                    // signature is 65 bytes, this will be the real `v` value.
                    // If not, it will need to be modified - doing it this way
                    // saves an extra condition.
                    v := byte(
                        0,
                        mload(add(signature, ECDSA_signature_v_offset))
                    )

                    // If lenDiff is 1, parse 64-byte signature as ECDSA.
                    if lenDiff {
                        // Extract yParity from highest bit of vs and add 27 to
                        // get v.
                        v := add(
                            shr(MaxUint8, originalSignatureS),
                            Signature_lower_v
                        )

                        // Extract canonical s from vs, all but the highest bit.
                        // Temporarily overwrite the original `s` value in the
                        // signature.
                        mstore(
                            add(signature, ECDSA_signature_s_offset),
                            and(
                                originalSignatureS,
                                EIP2098_allButHighestBitMask
                            )
                        )
                    }
                    // Temporarily overwrite the signature length with `v` to
                    // conform to the expected input for ecrecover.
                    mstore(signature, v)

                    // Temporarily overwrite the word before the length with
                    // `digest` to conform to the expected input for ecrecover.
                    mstore(wordBeforeSignaturePtr, digest)

                    // Attempt to recover the signer for the given signature. Do
                    // not check the call status as ecrecover will return a null
                    // address if the signature is invalid.
                    pop(
                        staticcall(
                            gas(),
                            Ecrecover_precompile, // Call ecrecover precompile.
                            wordBeforeSignaturePtr, // Use data memory location.
                            Ecrecover_args_size, // Size of digest, v, r, and s.
                            0, // Write result to scratch space.
                            OneWord // Provide size of returned result.
                        )
                    )

                    // Restore cached word before signature.
                    mstore(wordBeforeSignaturePtr, cachedWordBeforeSignature)

                    // Restore cached signature length.
                    mstore(signature, signatureLength)

                    // Restore cached signature `s` value.
                    mstore(
                        add(signature, ECDSA_signature_s_offset),
                        originalSignatureS
                    )

                    // Read the recovered signer from the buffer given as return
                    // space for ecrecover.
                    recoveredSigner := mload(0)
                }
            }

            // Restore the cached values overwritten by selector, digest and
            // signature head.
            mstore(wordBeforeSignaturePtr, cachedWordBeforeSignature)
        }
    }

    /**
     * @dev Internal view function to get the EIP-712 domain separator. If the
     *      chainId matches the chainId set on deployment, the cached domain
     *      separator will be returned; otherwise, it will be derived from
     *      scratch.
     *
     * @return The domain separator.
     */
    function _domainSeparator() internal view returns (bytes32) {
        // prettier-ignore
        return block.chainid == _CHAIN_ID
            ? _DOMAIN_SEPARATOR
            : _deriveDomainSeparator();
    }

    /**
     * @dev Internal view function to derive the EIP-712 domain separator.
     *
     * @return domainSeparator The derived domain separator.
     */
    function _deriveDomainSeparator()
        internal
        view
        returns (bytes32 domainSeparator)
    {
        bytes32 typehash = _EIP_712_DOMAIN_TYPEHASH;
        bytes32 nameHash = _NAME_HASH;
        bytes32 versionHash = _VERSION_HASH;

        // Leverage scratch space and other memory to perform an efficient hash.
        assembly {
            // Retrieve the free memory pointer; it will be replaced afterwards.
            let freeMemoryPointer := mload(FreeMemoryPointerSlot)

            // Retrieve value at 0x80; it will also be replaced afterwards.
            let slot0x80 := mload(Slot0x80)

            // Place typehash, name hash, and version hash at start of memory.
            mstore(0, typehash)
            mstore(OneWord, nameHash)
            mstore(TwoWords, versionHash)

            // Place chainId in the next memory location.
            mstore(ThreeWords, chainid())

            // Place the address of this contract in the next memory location.
            mstore(FourWords, address())

            // Hash relevant region of memory to derive the domain separator.
            domainSeparator := keccak256(0, FiveWords)

            // Restore the free memory pointer.
            mstore(FreeMemoryPointerSlot, freeMemoryPointer)

            // Restore the zero slot to zero.
            mstore(ZeroSlot, 0)

            // Restore the value at 0x80.
            mstore(Slot0x80, slot0x80)
        }
    }

    /**
     * @dev Internal pure function to efficiently derive an digest to sign for
     *      an order in accordance with EIP-712.
     *
     * @param domainSeparator The domain separator.
     * @param signedOrderHash The signedOrder hash.
     *
     * @return digest The digest hash.
     */
    function _deriveEIP712Digest(
        bytes32 domainSeparator,
        bytes32 signedOrderHash
    ) internal pure returns (bytes32 digest) {
        // Leverage scratch space to perform an efficient hash.
        assembly {
            // Place the EIP-712 prefix at the start of scratch space.
            mstore(0, EIP_712_PREFIX)

            // Place the domain separator in the next region of scratch space.
            mstore(EIP712_DomainSeparator_offset, domainSeparator)

            // Place the signed order hash in scratch space, spilling into the
            // first two bytes of the free memory pointer — this should never be
            // set as memory cannot be expanded to that size, and will be
            // zeroed out after the hash is performed.
            mstore(EIP712_SignedOrderHash_offset, signedOrderHash)

            // Hash the relevant region
            digest := keccak256(0, EIP712_DigestPayload_size)

            // Clear out the dirtied bits in the memory pointer.
            mstore(EIP712_SignedOrderHash_offset, 0)
        }
    }

    /**
     * @dev Private view function to revert if the caller is not the
     *      controller.
     */
    function _assertCallerIsController() internal view {
        // Get the controller address to use in the assembly block.
        address controller = _controller;

        assembly {
            // Revert if the caller is not the controller.
            if iszero(eq(caller(), controller)) {
                // Store left-padded selector with push4, mem[28:32] = selector
                mstore(0, InvalidController_error_selector)
                // revert(abi.encodeWithSignature(
                //   "InvalidController()")
                // )
                revert(0x1c, InvalidController_error_length)
            }
        }
    }

    /**
     * @dev Internal pure function to validate calldata offsets for the
     *      dyanamic type in ZoneParameters. This ensures that functions using
     *      the calldata object normally will be using the same data as the
     *      assembly functions and that values that are bound to a given range
     *      are within that range.
     */
    function _assertValidZoneParameters() internal pure {
        // Utilize assembly in order to read offset data directly from calldata.
        assembly {
            /*
             * Checks:
             * 1. Zone parameters struct offset == 0x20
             */

            // Zone parameters at calldata 0x04 must have offset of 0x20.
            if iszero(
                eq(calldataload(Zone_parameters_cdPtr), Zone_parameters_ptr)
            ) {
                // Store left-padded selector with push4 (reduces bytecode), mem[28:32] = selector
                mstore(0, InvalidZoneParameterEncoding_error_selector)
                // revert(abi.encodeWithSignature("InvalidZoneParameterEncoding()"))
                revert(0x1c, InvalidZoneParameterEncoding_error_length)
            }
        }
    }

    /**
     * @dev Internal pure function to ensure that the context argument for the
     *      supplied extra data follows the substandard #1 format. Returns the
     *      expected fulfiller of the order for deriving the signed order hash.
     *
     * @param orderHash The order hash.
     *
     * @return expectedFulfiller The expected fulfiller of the order.
     */
    function _getExpectedFulfiller(bytes32 orderHash)
        internal
        pure
        returns (address expectedFulfiller)
    {
        // Revert if the expected fulfiller is not the zero address and does
        // not match the actual fulfiller
        assembly {
            // Get the actual fulfiller.
            let actualFulfiller := calldataload(Zone_parameters_fulfiller_cdPtr)
            let extraDataPtr := calldataload(Zone_extraData_cdPtr)

            // Get the expected fulfiller.
            expectedFulfiller := shr(
                96,
                calldataload(add(expectedFulfiller_offset, extraDataPtr))
            )

            // Revert if expected fulfiller is not the zero address and does
            // not match the actual fulfiller.
            if and(
                iszero(iszero(expectedFulfiller)),
                iszero(eq(expectedFulfiller, actualFulfiller))
            ) {
                // Store left-padded selector with push4, mem[28:32] = selector
                mstore(0, InvalidFulfiller_error_selector)
                mstore(
                    InvalidFulfiller_error_expectedFulfiller_ptr,
                    expectedFulfiller
                )
                mstore(
                    InvalidFulfiller_error_actualFulfiller_ptr,
                    actualFulfiller
                )
                mstore(InvalidFulfiller_error_orderHash_ptr, orderHash)
                // revert(abi.encodeWithSignature(
                //   "InvalidFulfiller(address,address,bytes32)", expectedFulfiller, actualFulfiller, orderHash)
                // )
                revert(0x1c, InvalidFulfiller_error_length)
            }
        }
    }

    /**
     * @dev Internal pure function to ensure that the context argument for the
     *      supplied extra data follows the substandard #1 format. Returns the
     *      expected fulfiller of the order for deriving the signed order hash.
     *
     */
    function _assertValidSubstandard(
        bytes32 considerationHash,
        bytes32 orderHash
    ) internal pure {
        // identifier does not match the actual consideration.
        assembly {
            let extraDataPtr := calldataload(Zone_extraData_cdPtr)
            let considerationPtr := calldataload(Zone_consideration_head_cdPtr)
            // Get the actual consideration.
            let actualConsideration := calldataload(
                add(actualConsideration_offset, considerationPtr)
            )

            // Get the expected consideration.
            let expectedConsiderationHash := calldataload(
                add(expectedConsideration_offset, extraDataPtr) //TODO rename
            )
            // Revert if expected consideration item does not match the actual
            // consideration item.
            if iszero(eq(considerationHash, expectedConsiderationHash)) {
                // Store left-padded selector with push4, mem[28:32] = selector
                mstore(0, InvalidConsideration_error_selector)
                mstore(
                    InvalidConsideration_error_expectedConsideration_ptr,
                    expectedConsiderationHash
                )
                mstore(
                    InvalidConsideration_error_actualConsideration_ptr,
                    actualConsideration
                )
                mstore(InvalidConsideration_error_orderHash_ptr, orderHash)
                // revert(abi.encodeWithSignature(
                //   "InvalidConsideration(uint256,uint256,bytes32)", expectedConsideration, actualConsideration, orderHash)
                // )
                revert(0x1c, InvalidConsideration_error_length)
            }
        }
    }

    /// @dev Calculates consideration hash
    function _deriveConsiderationHash(ReceivedItem[] calldata consideration)
        internal
        pure
        returns (bytes32)
    {
        uint256 numberOfItems = consideration.length;
        bytes32[] memory considerationHashes = new bytes32[](numberOfItems);
        for (uint256 i; i < numberOfItems; ) {
            considerationHashes[i] = _deriveReceivedItemHash(consideration[i]);
            unchecked {
                ++i;
            }
        }
        return
            keccak256(
                abi.encode(
                    CONSIDERATION_HASHTYPE,
                    keccak256(abi.encodePacked(considerationHashes))
                )
            );
    }

    /// @dev Calculates consideration item hash
    function _deriveReceivedItemHash(ReceivedItem calldata receivedItem)
        internal
        pure
        returns (bytes32)
    {
        return
            keccak256(
                abi.encode(
                    RECEIVED_ITEM_HASHTYPE,
                    receivedItem.itemType,
                    receivedItem.token,
                    receivedItem.identifier,
                    receivedItem.amount,
                    receivedItem.recipient
                )
            );
    }
}

File 2 of 8 : ZoneInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import { ZoneParameters, Schema } from "../lib/ConsiderationStructs.sol";

interface ZoneInterface {
    function validateOrder(
        ZoneParameters calldata zoneParameters
    ) external returns (bytes4 validOrderMagicValue);

    function getSeaportMetadata()
        external
        view
        returns (
            string memory name,
            Schema[] memory schemas // map to Seaport Improvement Proposal IDs
        );
}

File 3 of 8 : ConsiderationEnums.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

// prettier-ignore
enum OrderType {
    // 0: no partial fills, anyone can execute
    FULL_OPEN,

    // 1: partial fills supported, anyone can execute
    PARTIAL_OPEN,

    // 2: no partial fills, only offerer or zone can execute
    FULL_RESTRICTED,

    // 3: partial fills supported, only offerer or zone can execute
    PARTIAL_RESTRICTED,

    // 4: contract order type
    CONTRACT
}

// prettier-ignore
enum BasicOrderType {
    // 0: no partial fills, anyone can execute
    ETH_TO_ERC721_FULL_OPEN,

    // 1: partial fills supported, anyone can execute
    ETH_TO_ERC721_PARTIAL_OPEN,

    // 2: no partial fills, only offerer or zone can execute
    ETH_TO_ERC721_FULL_RESTRICTED,

    // 3: partial fills supported, only offerer or zone can execute
    ETH_TO_ERC721_PARTIAL_RESTRICTED,

    // 4: no partial fills, anyone can execute
    ETH_TO_ERC1155_FULL_OPEN,

    // 5: partial fills supported, anyone can execute
    ETH_TO_ERC1155_PARTIAL_OPEN,

    // 6: no partial fills, only offerer or zone can execute
    ETH_TO_ERC1155_FULL_RESTRICTED,

    // 7: partial fills supported, only offerer or zone can execute
    ETH_TO_ERC1155_PARTIAL_RESTRICTED,

    // 8: no partial fills, anyone can execute
    ERC20_TO_ERC721_FULL_OPEN,

    // 9: partial fills supported, anyone can execute
    ERC20_TO_ERC721_PARTIAL_OPEN,

    // 10: no partial fills, only offerer or zone can execute
    ERC20_TO_ERC721_FULL_RESTRICTED,

    // 11: partial fills supported, only offerer or zone can execute
    ERC20_TO_ERC721_PARTIAL_RESTRICTED,

    // 12: no partial fills, anyone can execute
    ERC20_TO_ERC1155_FULL_OPEN,

    // 13: partial fills supported, anyone can execute
    ERC20_TO_ERC1155_PARTIAL_OPEN,

    // 14: no partial fills, only offerer or zone can execute
    ERC20_TO_ERC1155_FULL_RESTRICTED,

    // 15: partial fills supported, only offerer or zone can execute
    ERC20_TO_ERC1155_PARTIAL_RESTRICTED,

    // 16: no partial fills, anyone can execute
    ERC721_TO_ERC20_FULL_OPEN,

    // 17: partial fills supported, anyone can execute
    ERC721_TO_ERC20_PARTIAL_OPEN,

    // 18: no partial fills, only offerer or zone can execute
    ERC721_TO_ERC20_FULL_RESTRICTED,

    // 19: partial fills supported, only offerer or zone can execute
    ERC721_TO_ERC20_PARTIAL_RESTRICTED,

    // 20: no partial fills, anyone can execute
    ERC1155_TO_ERC20_FULL_OPEN,

    // 21: partial fills supported, anyone can execute
    ERC1155_TO_ERC20_PARTIAL_OPEN,

    // 22: no partial fills, only offerer or zone can execute
    ERC1155_TO_ERC20_FULL_RESTRICTED,

    // 23: partial fills supported, only offerer or zone can execute
    ERC1155_TO_ERC20_PARTIAL_RESTRICTED
}

// prettier-ignore
enum BasicOrderRouteType {
    // 0: provide Ether (or other native token) to receive offered ERC721 item.
    ETH_TO_ERC721,

    // 1: provide Ether (or other native token) to receive offered ERC1155 item.
    ETH_TO_ERC1155,

    // 2: provide ERC20 item to receive offered ERC721 item.
    ERC20_TO_ERC721,

    // 3: provide ERC20 item to receive offered ERC1155 item.
    ERC20_TO_ERC1155,

    // 4: provide ERC721 item to receive offered ERC20 item.
    ERC721_TO_ERC20,

    // 5: provide ERC1155 item to receive offered ERC20 item.
    ERC1155_TO_ERC20
}

// prettier-ignore
enum ItemType {
    // 0: ETH on mainnet, MATIC on polygon, etc.
    NATIVE,

    // 1: ERC20 items (ERC777 and ERC20 analogues could also technically work)
    ERC20,

    // 2: ERC721 items
    ERC721,

    // 3: ERC1155 items
    ERC1155,

    // 4: ERC721 items where a number of tokenIds are supported
    ERC721_WITH_CRITERIA,

    // 5: ERC1155 items where a number of ids are supported
    ERC1155_WITH_CRITERIA
}

// prettier-ignore
enum Side {
    // 0: Items that can be spent
    OFFER,

    // 1: Items that must be received
    CONSIDERATION
}

File 4 of 8 : ConsiderationStructs.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import { OrderType, BasicOrderType, ItemType, Side } from "./ConsiderationEnums.sol";

/**
 * @dev An order contains eleven components: an offerer, a zone (or account that
 *      can cancel the order or restrict who can fulfill the order depending on
 *      the type), the order type (specifying partial fill support as well as
 *      restricted order status), the start and end time, a hash that will be
 *      provided to the zone when validating restricted orders, a salt, a key
 *      corresponding to a given conduit, a counter, and an arbitrary number of
 *      offer items that can be spent along with consideration items that must
 *      be received by their respective recipient.
 */
struct OrderComponents {
    address offerer;
    address zone;
    OfferItem[] offer;
    ConsiderationItem[] consideration;
    OrderType orderType;
    uint256 startTime;
    uint256 endTime;
    bytes32 zoneHash;
    uint256 salt;
    bytes32 conduitKey;
    uint256 counter;
}

/**
 * @dev An offer item has five components: an item type (ETH or other native
 *      tokens, ERC20, ERC721, and ERC1155, as well as criteria-based ERC721 and
 *      ERC1155), a token address, a dual-purpose "identifierOrCriteria"
 *      component that will either represent a tokenId or a merkle root
 *      depending on the item type, and a start and end amount that support
 *      increasing or decreasing amounts over the duration of the respective
 *      order.
 */
struct OfferItem {
    ItemType itemType;
    address token;
    uint256 identifierOrCriteria;
    uint256 startAmount;
    uint256 endAmount;
}

/**
 * @dev A consideration item has the same five components as an offer item and
 *      an additional sixth component designating the required recipient of the
 *      item.
 */
struct ConsiderationItem {
    ItemType itemType;
    address token;
    uint256 identifierOrCriteria;
    uint256 startAmount;
    uint256 endAmount;
    address payable recipient;
}

/**
 * @dev A spent item is translated from a utilized offer item and has four
 *      components: an item type (ETH or other native tokens, ERC20, ERC721, and
 *      ERC1155), a token address, a tokenId, and an amount.
 */
struct SpentItem {
    ItemType itemType;
    address token;
    uint256 identifier;
    uint256 amount;
}

/**
 * @dev A received item is translated from a utilized consideration item and has
 *      the same four components as a spent item, as well as an additional fifth
 *      component designating the required recipient of the item.
 */
struct ReceivedItem {
    ItemType itemType;
    address token;
    uint256 identifier;
    uint256 amount;
    address payable recipient;
}

/**
 * @dev For basic orders involving ETH / native / ERC20 <=> ERC721 / ERC1155
 *      matching, a group of six functions may be called that only requires a
 *      subset of the usual order arguments. Note the use of a "basicOrderType"
 *      enum; this represents both the usual order type as well as the "route"
 *      of the basic order (a simple derivation function for the basic order
 *      type is `basicOrderType = orderType + (4 * basicOrderRoute)`.)
 */
struct BasicOrderParameters {
    // calldata offset
    address considerationToken; // 0x24
    uint256 considerationIdentifier; // 0x44
    uint256 considerationAmount; // 0x64
    address payable offerer; // 0x84
    address zone; // 0xa4
    address offerToken; // 0xc4
    uint256 offerIdentifier; // 0xe4
    uint256 offerAmount; // 0x104
    BasicOrderType basicOrderType; // 0x124
    uint256 startTime; // 0x144
    uint256 endTime; // 0x164
    bytes32 zoneHash; // 0x184
    uint256 salt; // 0x1a4
    bytes32 offererConduitKey; // 0x1c4
    bytes32 fulfillerConduitKey; // 0x1e4
    uint256 totalOriginalAdditionalRecipients; // 0x204
    AdditionalRecipient[] additionalRecipients; // 0x224
    bytes signature; // 0x244
    // Total length, excluding dynamic array data: 0x264 (580)
}

/**
 * @dev Basic orders can supply any number of additional recipients, with the
 *      implied assumption that they are supplied from the offered ETH (or other
 *      native token) or ERC20 token for the order.
 */
struct AdditionalRecipient {
    uint256 amount;
    address payable recipient;
}

/**
 * @dev The full set of order components, with the exception of the counter,
 *      must be supplied when fulfilling more sophisticated orders or groups of
 *      orders. The total number of original consideration items must also be
 *      supplied, as the caller may specify additional consideration items.
 */
struct OrderParameters {
    address offerer; // 0x00
    address zone; // 0x20
    OfferItem[] offer; // 0x40
    ConsiderationItem[] consideration; // 0x60
    OrderType orderType; // 0x80
    uint256 startTime; // 0xa0
    uint256 endTime; // 0xc0
    bytes32 zoneHash; // 0xe0
    uint256 salt; // 0x100
    bytes32 conduitKey; // 0x120
    uint256 totalOriginalConsiderationItems; // 0x140
    // offer.length                          // 0x160
}

/**
 * @dev Orders require a signature in addition to the other order parameters.
 */
struct Order {
    OrderParameters parameters;
    bytes signature;
}

/**
 * @dev Advanced orders include a numerator (i.e. a fraction to attempt to fill)
 *      and a denominator (the total size of the order) in addition to the
 *      signature and other order parameters. It also supports an optional field
 *      for supplying extra data; this data will be provided to the zone if the
 *      order type is restricted and the zone is not the caller, or will be
 *      provided to the offerer as context for contract order types.
 */
struct AdvancedOrder {
    OrderParameters parameters;
    uint120 numerator;
    uint120 denominator;
    bytes signature;
    bytes extraData;
}

/**
 * @dev Orders can be validated (either explicitly via `validate`, or as a
 *      consequence of a full or partial fill), specifically cancelled (they can
 *      also be cancelled in bulk via incrementing a per-zone counter), and
 *      partially or fully filled (with the fraction filled represented by a
 *      numerator and denominator).
 */
struct OrderStatus {
    bool isValidated;
    bool isCancelled;
    uint120 numerator;
    uint120 denominator;
}

/**
 * @dev A criteria resolver specifies an order, side (offer vs. consideration),
 *      and item index. It then provides a chosen identifier (i.e. tokenId)
 *      alongside a merkle proof demonstrating the identifier meets the required
 *      criteria.
 */
struct CriteriaResolver {
    uint256 orderIndex;
    Side side;
    uint256 index;
    uint256 identifier;
    bytes32[] criteriaProof;
}

/**
 * @dev A fulfillment is applied to a group of orders. It decrements a series of
 *      offer and consideration items, then generates a single execution
 *      element. A given fulfillment can be applied to as many offer and
 *      consideration items as desired, but must contain at least one offer and
 *      at least one consideration that match. The fulfillment must also remain
 *      consistent on all key parameters across all offer items (same offerer,
 *      token, type, tokenId, and conduit preference) as well as across all
 *      consideration items (token, type, tokenId, and recipient).
 */
struct Fulfillment {
    FulfillmentComponent[] offerComponents;
    FulfillmentComponent[] considerationComponents;
}

/**
 * @dev Each fulfillment component contains one index referencing a specific
 *      order and another referencing a specific offer or consideration item.
 */
struct FulfillmentComponent {
    uint256 orderIndex;
    uint256 itemIndex;
}

/**
 * @dev An execution is triggered once all consideration items have been zeroed
 *      out. It sends the item in question from the offerer to the item's
 *      recipient, optionally sourcing approvals from either this contract
 *      directly or from the offerer's chosen conduit if one is specified. An
 *      execution is not provided as an argument, but rather is derived via
 *      orders, criteria resolvers, and fulfillments (where the total number of
 *      executions will be less than or equal to the total number of indicated
 *      fulfillments) and returned as part of `matchOrders`.
 */
struct Execution {
    ReceivedItem item;
    address offerer;
    bytes32 conduitKey;
}

/**
 * @dev Restricted orders are validated post-execution by calling validateOrder
 *      on the zone. This struct provides context about the order fulfillment
 *      and any supplied extraData, as well as all order hashes fulfilled in a
 *      call to a match or fulfillAvailable method.
 */
struct ZoneParameters {
    bytes32 orderHash;
    address fulfiller;
    address offerer;
    SpentItem[] offer;
    ReceivedItem[] consideration;
    bytes extraData;
    bytes32[] orderHashes;
    uint256 startTime;
    uint256 endTime;
    bytes32 zoneHash;
}

/**
 * @dev Zones and contract offerers can communicate which schemas they implement
 *      along with any associated metadata related to each schema.
 */
struct Schema {
    uint256 id;
    bytes metadata;
}

File 5 of 8 : SignedZoneControllerInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

/**
 * @title  SignedZoneControllerInterface
 * @author BCLeFevre
 * @notice SignedZoneControllerInterface enables the deploying of SignedZones.
 *         SignedZones are an implementation of SIP-7 that requires orders
 *         to be signed by an approved signer.
 *         https://github.com/ProjectOpenSea/SIPs/blob/main/SIPS/sip-7.md
 *
 */
interface SignedZoneControllerInterface {
    /**
     * @notice Deploy a SignedZone to a precomputed address.
     *
     * @param zoneName    The name for the zone returned in
     *                    getSeaportMetadata().
     * @param apiEndpoint The API endpoint where orders for this zone can be
     *                    signed.
     * @param documentationURI The URI to the documentation describing the
     *                         behavior of the contract.
     *                    Request and response payloads are defined in SIP-7.
     * @param salt        The salt to be used to derive the zone address
     * @param initialOwner The initial owner to set for the new zone.
     *
     * @return derivedAddress The derived address for the zone.
     */
    function createZone(
        string memory zoneName,
        string memory apiEndpoint,
        string memory documentationURI,
        address initialOwner,
        bytes32 salt
    ) external returns (address derivedAddress);

    /**
     * @notice Returns the active signers for the zone.
     *
     * @param signedZone The signed zone to get the active signers for.
     *
     * @return signers The active signers.
     */
    function getActiveSigners(address signedZone)
        external
        view
        returns (address[] memory signers);

    /**
     * @notice Returns additional information about the zone.
     *
     * @param zone The zone to get the additional information for.
     *
     * @return domainSeparator  The domain separator used for signing.
     * @return zoneName         The name of the zone.
     * @return apiEndpoint      The API endpoint for the zone.
     * @return substandards     The substandards supported by the zone.
     * @return documentationURI The documentation URI for the zone.
     */
    function getAdditionalZoneInformation(address zone)
        external
        view
        returns (
            bytes32 domainSeparator,
            string memory zoneName,
            string memory apiEndpoint,
            uint256[] memory substandards,
            string memory documentationURI
        );

    /**
     * @notice Update the API endpoint returned by the supplied zone.
     *         Only the owner or an active signer can call this function.
     *
     * @param signedZone    The signed zone to update the API endpoint for.
     * @param newApiEndpoint The new API endpoint.
     */
    function updateAPIEndpoint(
        address signedZone,
        string calldata newApiEndpoint
    ) external;

    /**
     * @notice Update the signer for a given signed zone.
     *
     * @param signedZone The signed zone to update the signer for.
     * @param signer     The signer to update.
     * @param active     If the signer should be active or not.
     */
    function updateSigner(
        address signedZone,
        address signer,
        bool active
    ) external;

    /**
     * @notice Initiate zone ownership transfer by assigning a new potential
     *         owner for the given zone. Once set, the new potential owner
     *         may call `acceptOwnership` to claim ownership of the zone.
     *         Only the owner of the zone in question may call this function.
     *
     * @param zone The zone for which to initiate ownership transfer.
     * @param newPotentialOwner The new potential owner of the zone.
     */
    function transferOwnership(address zone, address newPotentialOwner)
        external;

    /**
     * @notice Clear the currently set potential owner, if any, from a zone.
     *         Only the owner of the zone in question may call this function.
     *
     * @param zone The zone for which to cancel ownership transfer.
     */
    function cancelOwnershipTransfer(address zone) external;

    /**
     * @notice Accept ownership of a supplied zone. Only accounts that the
     *         current owner has set as the new potential owner may call this
     *         function.
     *
     * @param zone The zone for which to accept ownership.
     */
    function acceptOwnership(address zone) external;

    /**
     * @notice Retrieve the current owner of a deployed zone.
     *
     * @param zone The zone for which to retrieve the associated owner.
     *
     * @return owner The owner of the supplied zone.
     */
    function ownerOf(address zone) external view returns (address owner);

    /**
     * @notice Retrieve the potential owner, if any, for a given zone. The
     *         current owner may set a new potential owner via
     *         `transferOwnership` and that owner may then accept ownership of
     *         the zone in question via `acceptOwnership`.
     *
     * @param zone The zone for which to retrieve the potential owner.
     *
     * @return potentialOwner The potential owner, if any, for the zone.
     */
    function getPotentialOwner(address zone)
        external
        view
        returns (address potentialOwner);

    /**
     * @notice Derive the zone address associated with a salt.
     *
     * @param salt        The salt to be used to derive the zone address
     *
     * @return derivedAddress The derived address of the signed zone.
     */
    function getZone(bytes32 salt)
        external
        view
        returns (address derivedAddress);
}

File 6 of 8 : SignedZoneEventsAndErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

/**
 * @notice SignedZoneEventsAndErrors contains errors and events
 *         related to zone interaction.
 */
interface SignedZoneEventsAndErrors {
    /**
     * @dev Emit an event when a new signer is added.
     */
    event SignerAdded(address signer);

    /**
     * @dev Emit an event when a signer is removed.
     */
    event SignerRemoved(address signer);

    /**
     * @dev Revert with an error if msg.sender is not the owner
     *      or an active signer.
     */
    error OnlyOwnerOrActiveSigner();

    /**
     * @dev Revert with an error when the signature has expired.
     */
    error SignatureExpired(uint256 expiration, bytes32 orderHash);

    /**
     * @dev Revert with an error when attempting to update the signers of a
     *      the zone from a caller that is not the zone's controller.
     */
    error InvalidController();

    /**
     * @dev Revert with an error if supplied order extraData is an invalid
     *      length.
     */
    error InvalidExtraDataLength(bytes32 orderHash);

    /**
     * @dev Revert with an error if the supplied order extraData does not
     *      support the zone's SIP6 version.
     */
    error InvalidSIP6Version(bytes32 orderHash);

    /**
     * @dev Revert with an error if the supplied order extraData does not
     *      support the zone's substandard requirements.
     */
    error InvalidSubstandardSupport(
        string reason,
        uint256 substandardVersion,
        bytes32 orderHash
    );

    /**
     * @dev Revert with an error if the supplied order extraData does not
     *      support the zone's substandard version.
     */
    error InvalidSubstandardVersion(bytes32 orderHash);

    /**
     * @dev Revert with an error if the fulfiller does not match.
     */
    error InvalidFulfiller(
        address expectedFulfiller,
        address actualFulfiller,
        bytes32 orderHash
    );

    /**
     * @dev Revert with an error if the consideration does not match.
     */
    error InvalidConsideration(
        uint256 expectedConsiderationHash,
        uint256 actualConsiderationHash,
        bytes32 orderHash
    );

    /**
     * @dev Revert with an error if the zone parameter encoding is invalid.
     */
    error InvalidZoneParameterEncoding();

    /**
     * @dev Revert with an error when an order is signed with a signer
     *      that is not active.
     */
    error SignerNotActive(address signer, bytes32 orderHash);
}

File 7 of 8 : SIP5Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import { Schema } from "../../lib/ConsiderationStructs.sol";

/**
 * @dev SIP-5: Contract Metadata Interface for Seaport Contracts
 *      https://github.com/ProjectOpenSea/SIPs/blob/main/SIPS/sip-5.md
 */
interface SIP5Interface {
    /**
     * @dev An event that is emitted when a SIP-5 compatible contract is deployed.
     */
    event SeaportCompatibleContractDeployed();

    /**
     * @dev Returns Seaport metadata for this contract, returning the
     *      contract name and supported schemas.
     *
     * @return name    The contract name
     * @return schemas The supported SIPs
     */
    function getSeaportMetadata()
        external
        view
        returns (string memory name, Schema[] memory schemas);
}

File 8 of 8 : SignedZoneConstants.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

/// @dev ECDSA signature offsets.
uint256 constant ECDSA_MaxLength = 65;
uint256 constant ECDSA_signature_s_offset = 0x40;
uint256 constant ECDSA_signature_v_offset = 0x60;

/// @dev Helpers for memory offsets.
uint256 constant OneWord = 0x20;
uint256 constant TwoWords = 0x40;
uint256 constant ThreeWords = 0x60;
uint256 constant FourWords = 0x80;
uint256 constant FiveWords = 0xa0;
uint256 constant Signature_lower_v = 27;
uint256 constant MaxUint8 = 0xff;
bytes32 constant EIP2098_allButHighestBitMask = (
    0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
);
uint256 constant Ecrecover_precompile = 1;
uint256 constant Ecrecover_args_size = 0x80;
uint256 constant FreeMemoryPointerSlot = 0x40;
uint256 constant ZeroSlot = 0x60;
uint256 constant Slot0x80 = 0x80;

/// @dev The EIP-712 digest offsets.
uint256 constant EIP712_DomainSeparator_offset = 0x02;
uint256 constant EIP712_SignedOrderHash_offset = 0x22;
uint256 constant EIP712_DigestPayload_size = 0x42;
uint256 constant EIP_712_PREFIX = (
    0x1901000000000000000000000000000000000000000000000000000000000000
);

/*
 *  error InvalidController()
 *    - Defined in SignedZoneEventsAndErrors.sol
 *  Memory layout:
 *    - 0x00: Left-padded selector (data begins at 0x1c)
 * Revert buffer is memory[0x1c:0x20]
 */
uint256 constant InvalidController_error_selector = 0x6d5769be;
uint256 constant InvalidController_error_length = 0x04;

/*
 *  error InvalidFulfiller(address expectedFulfiller, address actualFulfiller, bytes32 orderHash)
 *    - Defined in SignedZoneEventsAndErrors.sol
 *  Memory layout:
 *    - 0x00: Left-padded selector (data begins at 0x1c)
 *    - 0x20: expectedFulfiller
 *    - 0x40: actualFullfiller
 *    - 0x60: orderHash
 * Revert buffer is memory[0x1c:0x80]
 */
uint256 constant InvalidFulfiller_error_selector = 0x1bcf9bb7;
uint256 constant InvalidFulfiller_error_expectedFulfiller_ptr = 0x20;
uint256 constant InvalidFulfiller_error_actualFulfiller_ptr = 0x40;
uint256 constant InvalidFulfiller_error_orderHash_ptr = 0x60;
uint256 constant InvalidFulfiller_error_length = 0x64;

/*
 *  error InvalidConsideration(uint256 expectedConsideration, uint256 actualConsideration, bytes32 orderHash)
 *    - Defined in SignedZoneEventsAndErrors.sol
 *  Memory layout:
 *    - 0x00: Left-padded selector (data begins at 0x1c)
 *    - 0x20: expectedConsideration
 *    - 0x40: actualConsideration
 *    - 0x60: orderHash
 * Revert buffer is memory[0x1c:0x80]
 */
uint256 constant InvalidConsideration_error_selector = 0x59cb96d1;
uint256 constant InvalidConsideration_error_expectedConsideration_ptr = 0x20;
uint256 constant InvalidConsideration_error_actualConsideration_ptr = 0x40;
uint256 constant InvalidConsideration_error_orderHash_ptr = 0x60;
uint256 constant InvalidConsideration_error_length = 0x64;

/*
 *  error InvalidZoneParameterEncoding()
 *    - Defined in SignedZoneEventsAndErrors.sol
 *  Memory layout:
 *    - 0x00: Left-padded selector (data begins at 0x1c)
 * Revert buffer is memory[0x1c:0x20]
 */
uint256 constant InvalidZoneParameterEncoding_error_selector = 0x46d5d895;
uint256 constant InvalidZoneParameterEncoding_error_length = 0x04;

/*
 * error InvalidExtraDataLength()
 *   - Defined in SignedZoneEventsAndErrors.sol
 * Memory layout:
 *   - 0x00: Left-padded selector (data begins at 0x1c)
 *   - 0x20: orderHash
 * Revert buffer is memory[0x1c:0x40]
 */
uint256 constant InvalidExtraDataLength_error_selector = 0xd232fd2c;
uint256 constant InvalidExtraDataLength_error_orderHash_ptr = 0x20;
uint256 constant InvalidExtraDataLength_error_length = 0x24;
uint256 constant InvalidExtraDataLength_epected_length = 0x7e;

uint256 constant ExtraData_expiration_offset = 0x35;
uint256 constant ExtraData_substandard_version_byte_offset = 0x7d;
/*
 *  error InvalidSIP6Version()
 *    - Defined in SignedZoneEventsAndErrors.sol
 *  Memory layout:
 *    - 0x00: Left-padded selector (data begins at 0x1c)
 *    - 0x20: orderHash
 * Revert buffer is memory[0x1c:0x40]
 */
uint256 constant InvalidSIP6Version_error_selector = 0x64115774;
uint256 constant InvalidSIP6Version_error_orderHash_ptr = 0x20;
uint256 constant InvalidSIP6Version_error_length = 0x24;

/*
 *  error InvalidSubstandardVersion()
 *    - Defined in SignedZoneEventsAndErrors.sol
 *  Memory layout:
 *    - 0x00: Left-padded selector (data begins at 0x1c)
 *    - 0x20: orderHash
 * Revert buffer is memory[0x1c:0x40]
 */
uint256 constant InvalidSubstandardVersion_error_selector = 0x26787999;
uint256 constant InvalidSubstandardVersion_error_orderHash_ptr = 0x20;
uint256 constant InvalidSubstandardVersion_error_length = 0x24;

/*
 *  error InvalidSubstandardSupport()
 *    - Defined in SignedZoneEventsAndErrors.sol
 *  Memory layout:
 *    - 0x00: Left-padded selector (data begins at 0x1c)
 *    - 0x20: reason
 *    - 0x40: substandardVersion
 *    - 0x60: orderHash
 * Revert buffer is memory[0x1c:0xe0]
 */
uint256 constant InvalidSubstandardSupport_error_selector = 0x2be76224;
uint256 constant InvalidSubstandardSupport_error_reason_offset_ptr = 0x20;
uint256 constant InvalidSubstandardSupport_error_substandard_version_ptr = 0x40;
uint256 constant InvalidSubstandardSupport_error_orderHash_ptr = 0x60;
uint256 constant InvalidSubstandardSupport_error_reason_length_ptr = 0x80;
uint256 constant InvalidSubstandardSupport_error_reason_ptr = 0xa0;
uint256 constant InvalidSubstandardSupport_error_reason_2_ptr = 0xc0;
uint256 constant InvalidSubstandardSupport_error_length = 0xc4;

/*
 * error SignatureExpired()
 *   - Defined in SignedZoneEventsAndErrors.sol
 * Memory layout:
 *   - 0x00: Left-padded selector (data begins at 0x1c)
 *   - 0x20: expiration
 *   - 0x40: orderHash
 * Revert buffer is memory[0x1c:0x60]
 */
uint256 constant SignatureExpired_error_selector = 0x16546071;
uint256 constant SignatureExpired_error_expiration_ptr = 0x20;
uint256 constant SignatureExpired_error_orderHash_ptr = 0x40;
uint256 constant SignatureExpired_error_length = 0x44;

// Zone parameter calldata pointers
uint256 constant Zone_parameters_cdPtr = 0x04;
uint256 constant Zone_parameters_fulfiller_cdPtr = 0x44;
uint256 constant Zone_consideration_head_cdPtr = 0xa4;
uint256 constant Zone_extraData_cdPtr = 0xc4;

// Zone parameter memory pointers
uint256 constant Zone_parameters_ptr = 0x20;

// Zone parameter offsets
uint256 constant Zone_parameters_offset = 0x24;
uint256 constant expectedFulfiller_offset = 0x45;
uint256 constant actualConsideration_offset = 0x84;
uint256 constant expectedConsideration_offset = 0xa2;

Settings
{
  "viaIR": true,
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"expectedConsiderationHash","type":"uint256"},{"internalType":"uint256","name":"actualConsiderationHash","type":"uint256"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"InvalidConsideration","type":"error"},{"inputs":[],"name":"InvalidController","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"InvalidExtraDataLength","type":"error"},{"inputs":[{"internalType":"address","name":"expectedFulfiller","type":"address"},{"internalType":"address","name":"actualFulfiller","type":"address"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"InvalidFulfiller","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"InvalidSIP6Version","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"},{"internalType":"uint256","name":"substandardVersion","type":"uint256"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"InvalidSubstandardSupport","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"InvalidSubstandardVersion","type":"error"},{"inputs":[],"name":"InvalidZoneParameterEncoding","type":"error"},{"inputs":[],"name":"OnlyOwnerOrActiveSigner","type":"error"},{"inputs":[{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"SignatureExpired","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"SignerNotActive","type":"error"},{"anonymous":false,"inputs":[],"name":"SeaportCompatibleContractDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"SignerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"SignerRemoved","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"CONSIDERATION_BYTES","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONSIDERATION_HASHTYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECEIVED_ITEM_BYTES","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECEIVED_ITEM_HASHTYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSeaportMetadata","outputs":[{"internalType":"string","name":"name","type":"string"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct Schema[]","name":"schemas","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"address","name":"fulfiller","type":"address"},{"internalType":"address","name":"offerer","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct SpentItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ReceivedItem[]","name":"consideration","type":"tuple[]"},{"internalType":"bytes","name":"extraData","type":"bytes"},{"internalType":"bytes32[]","name":"orderHashes","type":"bytes32[]"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"}],"internalType":"struct ZoneParameters","name":"zoneParameters","type":"tuple"}],"name":"validateOrder","outputs":[{"internalType":"bytes4","name":"validOrderMagicValue","type":"bytes4"}],"stateMutability":"view","type":"function"}]

610160604052346200029f5762000015620002fa565b6020815191012060a0526200002962000322565b6020815191012060c0526040516020810181620000f3620000e6620000bd620000a1620000866200006e87600d906c08a92a06e626488dedac2d2dc5609b1b81520190565b6b1cdd1c9a5b99c81b985b594b60a21b8152600c0190565b6e1cdd1c9a5b99c81d995c9cda5bdb8b608a1b8152600f0190565b6f1d5a5b9d0c8d4d8818da185a5b92590b60821b815260100190565b7f6164647265737320766572696679696e67436f6e747261637400000000000000815260190190565b602960f81b815260010190565b039162000109601f1993848101835282620002d6565b51902060e052604051620001ce602082019282620001c1620000e6620001a86200018a6200016c6200014e8a600c906b0a6d2cedccac89ee4c8cae4560a31b81520190565b711859191c995cdcc8199d5b199a5b1b195c8b60721b815260120190565b711d5a5b9d0d8d08195e1c1a5c985d1a5bdb8b60721b815260120190565b71189e5d195ccccc881bdc99195c92185cda0b60721b815260120190565b6c189e5d195cc818dbdb9d195e1d609a1b8152600d0190565b03908101835282620002d6565b519020610100908152610120468152336080526200021c60e0519060a0519160c0516040519360805192600052602052604052466060523060805260a0600020926040526000606052608052565b610140908152604051917f98a7ac23945182ac62b68fbe5ba35cc0bf5c4c34b3a410ce94a4c2270282d6b5600080a16112649384620003468539608051848181610a4e01528181610b480152610d3d015260a05184610fc6015260c05184610fea015260e05184610fa301525183610e5201525182610f5001525181610f770152f35b600080fd5b604081019081106001600160401b03821117620002c057604052565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b03821190821017620002c057604052565b604051906200030982620002a4565b600a8252695369676e65645a6f6e6560b01b6020830152565b604051906200033182620002a4565b60058252640312e302e360dc1b602083015256fe6080604052600436101561001e575b610016610971565b602081519101f35b6000803560e01c9081630be2ebbe146100995750806317b1f942146100905780632e778efc1461008757806369c56dc91461007e578063c3b1e705146100755763d61d79d20361000e57610070610694565b61000e565b5061007061066a565b50610070610646565b50610070610482565b50610070610216565b346100c457806003193601126100c4576100c06100b4610142565b60405191829182610202565b0390f35b80fd5b50634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b038211176100f957604052565b6101016100c7565b604052565b60e081019081106001600160401b038211176100f957604052565b90601f801991011681019081106001600160401b038211176100f957604052565b6040516d086dedce6d2c8cae4c2e8d2dedc560931b60208201527f52656365697665644974656d5b5d20636f6e73696465726174696f6e00000000602e820152602960f81b604a820152602b8152606081018181106001600160401b038211176101ad575b60405290565b6101b56100c7565b6101a7565b60005b8381106101cd5750506000910152565b81810151838201526020016101bd565b906020916101f6815180928185528580860191016101ba565b601f01601f1916010190565b9060206102139281815201906101dd565b90565b50346103f6576003196020368201126103f6576004356001600160401b0381116103f657610140816004019282360301126103f657610253611025565b61026060a48201836106c5565b9083359360c435607e8160240135036103e457604481013560f81c6103d25760a181013560f81c6103c0576059013560c01c93854286106103ab578392610308926102e492610316986102c2896102ba816103109b6106f7565b9b9099610708565b949093836102cf8161103f565b9260a43560240135610384575b505050610e31565b6102ec610f4b565b61190160f01b6000526002526022526042600020906000602252565b9236916107ba565b90610ec5565b61034361033f6103388360018060a01b03166000526000602052604060002090565b5460ff1690565b1590565b61035957604051630bd8fca160e11b8152602090f35b6040516317c3008960e01b81526001600160a01b039190911660048201526024810191909152604490fd5b61039861039e9160846103a395019061075b565b906110f0565b611076565b3883816102dc565b8563165460716000526020526040526044601cfd5b8563267879996000526020526024601cfd5b8563641157746000526020526024601cfd5b8563d232fd2c6000526020526024601cfd5b600080fd5b61040d604092838352838301906101dd565b906020908181840391015283519182815281810182808560051b8401019601946000925b858410610442575050505050505090565b909192939495968580610471600193601f1986820301885286838d5180518452015191818582015201906101dd565b990194019401929594939190610431565b50346103f6576000806003193601126100c45760408051916104a3836100de565b60018352805b6020808210156104d6578351602092916104c2826100de565b8482526060818301528287010152016104a9565b8461051a6100c08660076104e98561082e565b515261050c6104f6610d16565b908698949398959295519586946020860161086a565b03601f198101835282610121565b60206105258661082e565b51015251928392836103fb565b6040516c0a4cac6cad2eccac892e8cada5609b1b60208201526e1d5a5b9d0e081a5d195b551e5c194b608a1b602d8201526d1859191c995cdcc81d1bdad95b8b60921b603c820152721d5a5b9d0c8d4d881a59195b9d1a599a595c8b606a1b604a8201526e1d5a5b9d0c8d4d88185b5bdd5b9d0b608a1b605d820152701859191c995cdcc81c9958da5c1a595b9d607a1b606c820152602960f81b607d820152605e8152608081018181106001600160401b038211176101ad5760405290565b6105fa610142565b610602610532565b610640602060405180938261062081840197888151938492016101ba565b8201610634825180938680850191016101ba565b01038084520182610121565b51902090565b50346103f65760003660031901126103f65760206106626105f2565b604051908152f35b50346103f65760003660031901126103f6576020610686610532565b818151910120604051908152f35b50346103f65760003660031901126103f6576100c06106b1610532565b6040519182916020835260208301906101dd565b903590601e19813603018212156103f657018035906001600160401b0382116103f6576020019181360383136103f657565b90605d116103f657601d0190604090565b9092919283605d116103f65783116103f657605d0191605c190190565b919091826004116103f65782116103f6576004916003190190565b919091826024116103f65782116103f6576024916023190190565b903590601e19813603018212156103f657018035906001600160401b0382116103f6576020019160a08202360383136103f657565b6020906001600160401b0381116107ad575b601f01601f19160190565b6107b56100c7565b6107a2565b9291926107c682610790565b916107d46040519384610121565b8294818452818301116103f6578281602093846000960137010152565b6020906001600160401b03811161080a575b60051b0190565b6108126100c7565b610803565b50634e487b7160e01b600052603260045260246000fd5b60209080511561083c570190565b610844610817565b0190565b602091815181101561085d575b60051b010190565b610865610817565b610855565b9094939194815261088760209560808784015260808301906101dd565b818103604083015285808551928381520194019060005b8181106108bb5750505061021393945060608184039101526101dd565b82518652948701949187019160010161089e565b908160209103126103f657356001600160e01b0319811681036103f65790565b6020908160408183019282815285518094520193019160005b828110610916575050505090565b83516001600160a01b031685529381019392810192600101610908565b6001600160a01b038116036103f657565b908160209103126103f6573561021381610933565b908160209103126103f6573580151581036103f65790565b6060906000356001600160e01b03191663f460590b60e01b81036109d457506109d26109b76109ab6109a33636610725565b810190610944565b6001600160a01b031690565b6109cc6109c43636610740565b810190610959565b90610a4b565b565b6329e12e0360e21b8103610a025750905061050c6102136109f3610b2c565b604051928391602083016108ef565b6301ffc9a760e01b14610a1157565b905061050c610213610a36610a31610a293636610725565b8101906108cf565b610c32565b60408051911515602083015290928391820190565b907f00000000000000000000000000000000000000000000000000000000000000003303610b115715610ac6576001600160a01b031660008181526020818152604091829020805460ff1916600117905590519182527f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f2491a1565b6001600160a01b031660008181526020818152604091829020805460ff1916905590519182527f3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b91a1565b636d5769be6000526004601cfd5b506040513d6000823e3d90fd5b6040516366a2489f60e01b8152306004820152600080826024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa918215610c25575b8192610b8557505090565b9091503d8083833e610b978183610121565b81016020918281830312610c1d578051906001600160401b038211610c21570181601f82011215610c1d57805190610bce826107f1565b94610bdc6040519687610121565b828652848087019360051b8301019384116100c457508301905b828210610c04575050505090565b8380918351610c1281610933565b815201910190610bf6565b8380fd5b8480fd5b610c2d610b1f565b610b7a565b63ffffffff60e01b16630b9de3bf60e21b8114908115610c65575b8115610c57575090565b6301ffc9a760e01b14919050565b631ce33bdf60e11b81149150610c4d565b81601f820112156103f6578051610c8c81610790565b92610c9a6040519485610121565b818452602082840101116103f65761021391602080850191016101ba565b81601f820112156103f657805191610ccf836107f1565b92610cdd6040519485610121565b808452602092838086019260051b8201019283116103f6578301905b828210610d07575050505090565b81518152908301908301610cf9565b610d1e610f4b565b604051628f139360e31b815230600482015290919060009081816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa918215610e24575b80928192828092610d83575b505090919293565b9350935050503d8082843e610d988184610121565b820160a083820312610e20576020830151906001600160401b0391828111610c1d5781610dc6918601610c76565b916040850151818111610c215782610ddf918701610c76565b946060810151828111610e1c5783610df8918301610cb8565b9460808201519283116100c45750610e11929101610c76565b909291903880610d7b565b8580fd5b5080fd5b610e2c610b1f565b610d6f565b9392610e4091929336916107ba565b602081519101206040519260208401947f0000000000000000000000000000000000000000000000000000000000000000865260018060a01b031660408501526001600160401b038093166060850152608084015260a083015260a0825260c082019082821090821117610eb8575b60405251902090565b610ec06100c7565b610eaf565b9190916000926000918280528151601f19830192835182604103946001861115610ef3575b50505050505050565b90919293949596975060408301948551966060850151891a90610f31575b8452815260208760808360015afa50525252519038808080808080610eea565b506001600160ff1b038716865260ff87901c601b01610f11565b6000467f000000000000000000000000000000000000000000000000000000000000000003610f9957507f000000000000000000000000000000000000000000000000000000000000000090565b60405190608051907f000000000000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006020527f0000000000000000000000000000000000000000000000000000000000000000604052466060523060805260a081209260405260605260805290565b60206004350361103157565b6346d5d8956000526004601cfd5b604560c435013560601c9190604435831515848214151661105e575050565b83631bcf9bb76000526020526040526060526064601cfd5b60c43560a20135809103611088575050565b6359cb96d160005260205260a435608401356040526060526064601cfd5b9160a0918110156110b657020190565b6110be610817565b020190565b805160208092019160005b8281106110dc575050505090565b8351855293810193928101926001016110ce565b906110fa816107f1565b916111086040519384610121565b818352601f199182611119826107f1565b0136602086013760005b8181106111895750505061064061117d9161113c6105f2565b9360405161115e816111526020820180956110c3565b03848101835282610121565b5190206040805160208101968752908101919091529283906060820190565b03908101835282610121565b8061119f61119a60019385876110a6565b6111b0565b6111a98288610848565b5201611123565b6111b8610532565b602081519101209080359060068210156103f6576020810135906111db82610933565b60606080820135916111ec83610933565b6040519460208601968752604086015260018060a01b038094168286015260408101356080860152013560a08401521660c082015260c081526106408161010656fea26469706673582212208c3ac49f92984f7585a000bab4069214cfa6a80c10fff39239f8be495179346c64736f6c63430008110033

Deployed Bytecode

0x6080604052600436101561001e575b610016610971565b602081519101f35b6000803560e01c9081630be2ebbe146100995750806317b1f942146100905780632e778efc1461008757806369c56dc91461007e578063c3b1e705146100755763d61d79d20361000e57610070610694565b61000e565b5061007061066a565b50610070610646565b50610070610482565b50610070610216565b346100c457806003193601126100c4576100c06100b4610142565b60405191829182610202565b0390f35b80fd5b50634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b038211176100f957604052565b6101016100c7565b604052565b60e081019081106001600160401b038211176100f957604052565b90601f801991011681019081106001600160401b038211176100f957604052565b6040516d086dedce6d2c8cae4c2e8d2dedc560931b60208201527f52656365697665644974656d5b5d20636f6e73696465726174696f6e00000000602e820152602960f81b604a820152602b8152606081018181106001600160401b038211176101ad575b60405290565b6101b56100c7565b6101a7565b60005b8381106101cd5750506000910152565b81810151838201526020016101bd565b906020916101f6815180928185528580860191016101ba565b601f01601f1916010190565b9060206102139281815201906101dd565b90565b50346103f6576003196020368201126103f6576004356001600160401b0381116103f657610140816004019282360301126103f657610253611025565b61026060a48201836106c5565b9083359360c435607e8160240135036103e457604481013560f81c6103d25760a181013560f81c6103c0576059013560c01c93854286106103ab578392610308926102e492610316986102c2896102ba816103109b6106f7565b9b9099610708565b949093836102cf8161103f565b9260a43560240135610384575b505050610e31565b6102ec610f4b565b61190160f01b6000526002526022526042600020906000602252565b9236916107ba565b90610ec5565b61034361033f6103388360018060a01b03166000526000602052604060002090565b5460ff1690565b1590565b61035957604051630bd8fca160e11b8152602090f35b6040516317c3008960e01b81526001600160a01b039190911660048201526024810191909152604490fd5b61039861039e9160846103a395019061075b565b906110f0565b611076565b3883816102dc565b8563165460716000526020526040526044601cfd5b8563267879996000526020526024601cfd5b8563641157746000526020526024601cfd5b8563d232fd2c6000526020526024601cfd5b600080fd5b61040d604092838352838301906101dd565b906020908181840391015283519182815281810182808560051b8401019601946000925b858410610442575050505050505090565b909192939495968580610471600193601f1986820301885286838d5180518452015191818582015201906101dd565b990194019401929594939190610431565b50346103f6576000806003193601126100c45760408051916104a3836100de565b60018352805b6020808210156104d6578351602092916104c2826100de565b8482526060818301528287010152016104a9565b8461051a6100c08660076104e98561082e565b515261050c6104f6610d16565b908698949398959295519586946020860161086a565b03601f198101835282610121565b60206105258661082e565b51015251928392836103fb565b6040516c0a4cac6cad2eccac892e8cada5609b1b60208201526e1d5a5b9d0e081a5d195b551e5c194b608a1b602d8201526d1859191c995cdcc81d1bdad95b8b60921b603c820152721d5a5b9d0c8d4d881a59195b9d1a599a595c8b606a1b604a8201526e1d5a5b9d0c8d4d88185b5bdd5b9d0b608a1b605d820152701859191c995cdcc81c9958da5c1a595b9d607a1b606c820152602960f81b607d820152605e8152608081018181106001600160401b038211176101ad5760405290565b6105fa610142565b610602610532565b610640602060405180938261062081840197888151938492016101ba565b8201610634825180938680850191016101ba565b01038084520182610121565b51902090565b50346103f65760003660031901126103f65760206106626105f2565b604051908152f35b50346103f65760003660031901126103f6576020610686610532565b818151910120604051908152f35b50346103f65760003660031901126103f6576100c06106b1610532565b6040519182916020835260208301906101dd565b903590601e19813603018212156103f657018035906001600160401b0382116103f6576020019181360383136103f657565b90605d116103f657601d0190604090565b9092919283605d116103f65783116103f657605d0191605c190190565b919091826004116103f65782116103f6576004916003190190565b919091826024116103f65782116103f6576024916023190190565b903590601e19813603018212156103f657018035906001600160401b0382116103f6576020019160a08202360383136103f657565b6020906001600160401b0381116107ad575b601f01601f19160190565b6107b56100c7565b6107a2565b9291926107c682610790565b916107d46040519384610121565b8294818452818301116103f6578281602093846000960137010152565b6020906001600160401b03811161080a575b60051b0190565b6108126100c7565b610803565b50634e487b7160e01b600052603260045260246000fd5b60209080511561083c570190565b610844610817565b0190565b602091815181101561085d575b60051b010190565b610865610817565b610855565b9094939194815261088760209560808784015260808301906101dd565b818103604083015285808551928381520194019060005b8181106108bb5750505061021393945060608184039101526101dd565b82518652948701949187019160010161089e565b908160209103126103f657356001600160e01b0319811681036103f65790565b6020908160408183019282815285518094520193019160005b828110610916575050505090565b83516001600160a01b031685529381019392810192600101610908565b6001600160a01b038116036103f657565b908160209103126103f6573561021381610933565b908160209103126103f6573580151581036103f65790565b6060906000356001600160e01b03191663f460590b60e01b81036109d457506109d26109b76109ab6109a33636610725565b810190610944565b6001600160a01b031690565b6109cc6109c43636610740565b810190610959565b90610a4b565b565b6329e12e0360e21b8103610a025750905061050c6102136109f3610b2c565b604051928391602083016108ef565b6301ffc9a760e01b14610a1157565b905061050c610213610a36610a31610a293636610725565b8101906108cf565b610c32565b60408051911515602083015290928391820190565b907f000000000000000000000000e1066481cc3b038badd0c68dfa5c8f163c3ff1923303610b115715610ac6576001600160a01b031660008181526020818152604091829020805460ff1916600117905590519182527f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f2491a1565b6001600160a01b031660008181526020818152604091829020805460ff1916905590519182527f3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b91a1565b636d5769be6000526004601cfd5b506040513d6000823e3d90fd5b6040516366a2489f60e01b8152306004820152600080826024817f000000000000000000000000e1066481cc3b038badd0c68dfa5c8f163c3ff1926001600160a01b03165afa918215610c25575b8192610b8557505090565b9091503d8083833e610b978183610121565b81016020918281830312610c1d578051906001600160401b038211610c21570181601f82011215610c1d57805190610bce826107f1565b94610bdc6040519687610121565b828652848087019360051b8301019384116100c457508301905b828210610c04575050505090565b8380918351610c1281610933565b815201910190610bf6565b8380fd5b8480fd5b610c2d610b1f565b610b7a565b63ffffffff60e01b16630b9de3bf60e21b8114908115610c65575b8115610c57575090565b6301ffc9a760e01b14919050565b631ce33bdf60e11b81149150610c4d565b81601f820112156103f6578051610c8c81610790565b92610c9a6040519485610121565b818452602082840101116103f65761021391602080850191016101ba565b81601f820112156103f657805191610ccf836107f1565b92610cdd6040519485610121565b808452602092838086019260051b8201019283116103f6578301905b828210610d07575050505090565b81518152908301908301610cf9565b610d1e610f4b565b604051628f139360e31b815230600482015290919060009081816024817f000000000000000000000000e1066481cc3b038badd0c68dfa5c8f163c3ff1926001600160a01b03165afa918215610e24575b80928192828092610d83575b505090919293565b9350935050503d8082843e610d988184610121565b820160a083820312610e20576020830151906001600160401b0391828111610c1d5781610dc6918601610c76565b916040850151818111610c215782610ddf918701610c76565b946060810151828111610e1c5783610df8918301610cb8565b9460808201519283116100c45750610e11929101610c76565b909291903880610d7b565b8580fd5b5080fd5b610e2c610b1f565b610d6f565b9392610e4091929336916107ba565b602081519101206040519260208401947f58d1345cbd7d0ceb38b86441d42a4086bc412b7f1ed7d947a569ed7d68b1b790865260018060a01b031660408501526001600160401b038093166060850152608084015260a083015260a0825260c082019082821090821117610eb8575b60405251902090565b610ec06100c7565b610eaf565b9190916000926000918280528151601f19830192835182604103946001861115610ef3575b50505050505050565b90919293949596975060408301948551966060850151891a90610f31575b8452815260208760808360015afa50525252519038808080808080610eea565b506001600160ff1b038716865260ff87901c601b01610f11565b6000467f000000000000000000000000000000000000000000000000000000000000000103610f9957507f65ef95f37774cb6487c6bbb0fae3a615f4fa8f5c10f450cc0e7fd7edde9d02e590565b60405190608051907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f0aa333075d560d6d2e102e9d7afe8a8ba8b4a3ec41e19473caad880f9eb5fbe66020527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c604052466060523060805260a081209260405260605260805290565b60206004350361103157565b6346d5d8956000526004601cfd5b604560c435013560601c9190604435831515848214151661105e575050565b83631bcf9bb76000526020526040526060526064601cfd5b60c43560a20135809103611088575050565b6359cb96d160005260205260a435608401356040526060526064601cfd5b9160a0918110156110b657020190565b6110be610817565b020190565b805160208092019160005b8281106110dc575050505090565b8351855293810193928101926001016110ce565b906110fa816107f1565b916111086040519384610121565b818352601f199182611119826107f1565b0136602086013760005b8181106111895750505061064061117d9161113c6105f2565b9360405161115e816111526020820180956110c3565b03848101835282610121565b5190206040805160208101968752908101919091529283906060820190565b03908101835282610121565b8061119f61119a60019385876110a6565b6111b0565b6111a98288610848565b5201611123565b6111b8610532565b602081519101209080359060068210156103f6576020810135906111db82610933565b60606080820135916111ec83610933565b6040519460208601968752604086015260018060a01b038094168286015260408101356080860152013560a08401521660c082015260c081526106408161010656fea26469706673582212208c3ac49f92984f7585a000bab4069214cfa6a80c10fff39239f8be495179346c64736f6c63430008110033

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

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.