APE Price: $1.30 (+2.02%)

Contract

0xB44D689Fa76ADfFFbcA5Ee35B073E80b2A9A68c6

Overview

APE Balance

Apechain LogoApechain LogoApechain Logo0 APE

APE Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Latest 1 internal transaction

Parent Transaction Hash Block From To
306992024-09-18 17:07:5566 days ago1726679275  Contract Creation0 APE

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SignedZoneV16Royalty

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

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

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

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

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

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

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

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

import "./lib/SignedZoneV16RoyaltyConstants.sol";

/**
 * @title  SignedZoneV16Royalty
 * @author ryanio, BCLeFevre
 * @notice SignedZoneV16Royalty 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
 */
contract SignedZoneV16Royalty is
  SignedZoneV16RoyaltyEventsAndErrors,
  ZoneInterfaceV16,
  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;
  bytes32 internal immutable _VERSION_HASH = keccak256(bytes("2.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",
            ")"
          )
        );
  uint256 internal immutable _CHAIN_ID = block.chainid;
  bytes32 internal immutable _DOMAIN_SEPARATOR;
  address private immutable SEAPORT = 0x0000000000000068F116a894984e2DB1123eB395;

  /**
   * @notice Constructor to deploy the contract.
   *
   * @param zoneName The name for the zone used in the domain separator
   *                 derivation.
   */
  constructor(string memory zoneName) {
    // Set the deployer as the controller.
    _controller = msg.sender;

    // Set the name hash.
    _NAME_HASH = keccak256(bytes(zoneName));

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

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

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

        if (selector == UPDATE_SIGNER_SELECTOR) {
            // abi.encodeWithSignature("updateSigner(address,bool)", signer,
            // active)
          
            // 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 == GET_ACTIVE_SIGNERS_SELECTOR) {
            // abi.encodeWithSignature("getActiveSigners()")
        
            // Call the internal function to get the active signers.
            return abi.encode(_getActiveSigners());
        } else if (selector == IS_ACTIVE_SIGNER_SELECTOR) {
            // abi.encodeWithSignature("isActiveSigner(address)", signer)

            // Get the signer.
            address signer = abi.decode(msg.data[4:], (address));

            // Call the internal function to determine if the signer is active.
            return abi.encode(_isActiveSigner(signer));
        }
        else {
             // Revert if the function selector is not supported.
            assembly {
                // Store left-padded selector with push4 (reduces bytecode),
                // mem[28:32] = selector
                mstore(0, UnsupportedFunctionSelector_error_selector)
                // revert(abi.encodeWithSignature(
                //  "UnsupportedFunctionSelector()"
                // ))
                revert(0x1c, UnsupportedFunctionSelector_error_length)
            }
        }
    }

  /**
   * @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 authorizedOrderMagicValue A magic value indicating if the order
   *                                   is currently valid.
   */
  function authorizeOrder(
    ZoneParameters calldata zoneParameters
  ) external override returns (bytes4 authorizedOrderMagicValue) {
    if (msg.sender != SEAPORT) {
      // Revert if the caller is not Seaport.
      revert CallerNotSeaport();
    }

    // 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;

    // Declare a variable to hold the expiration.
    uint64 expiration;

    // Declare a variable to hold the substandard version byte.
    uint256 subStandardVersionByte;

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

      // Validate the extra data length.
      if lt(extraDataLength, InvalidExtraDataLength_expected_length_substandard_1) {
        // 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)))

      // Validate the SIP6 Version byte.
      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, 0x01, 0x07, 0x08, or 0x09)
      subStandardVersionByte := shr(
        248,
        calldataload(add(extraDataPtr, ExtraData_substandard_version_byte_offset))
      )

      // Validate the substandard version byte.
      if or(
        gt(subStandardVersionByte, 0x09),
        and(gt(subStandardVersionByte, 0x01), lt(subStandardVersionByte, 0x07))
      ) {
        // 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.
      let considerationLength := calldataload(
        add(0x24, calldataload(Zone_consideration_head_cdPtr))
      )

      // Revert if the order does not have any consideration items due to
      // the Substandard #1 requirement.
      if iszero(considerationLength) {
        // Store left-padded selector with push4, mem[28:32] = selector
        mstore(0, InvalidSubstandardSupport_error_selector)
        mstore(InvalidSubstandardSupport_error_reason_offset_ptr, 0x60)
        mstore(InvalidSubstandardSupport_error_substandard_version_ptr, 1)
        mstore(InvalidSubstandardSupport_error_orderHash_ptr, orderHash)
        mstore(InvalidSubstandardSupport_error_reason_length_ptr, 0x2a)
        mstore(InvalidSubstandardSupport_error_reason_ptr, "Consideration must have at least")
        mstore(InvalidSubstandardSupport_error_reason_2_ptr, " one item.")
        // revert(abi.encodeWithSignature(
        //     "InvalidSubstandardSupport(string,uint256,bytes32)",
        //     reason,
        //     substandardVersion,
        //     orderHash
        // ))
        revert(0x1c, InvalidSubstandardSupport_error_length)
      }
    }

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

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

    // extraData bytes 93-126: context (fixed length, 32 bytes + 1 byte)
    bytes calldata context;

    if (subStandardVersionByte < 2) {
      context = extraData[93:126];
    } else if (subStandardVersionByte == 7) {
      if (extraData.length < 166) {
        assembly {
          // 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)
        }
      }
      context = extraData[93:166];
    } else {
      if (extraData.length < 146) {
        assembly {
          // 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)
        }
      }
      context = extraData[93:146];
    }

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

    // Set the transfer status of the tokens to true.
    _setTransferStatus(zoneParameters, true);

    // Return the selector of authorizeOrder as the magic value.
    authorizedOrderMagicValue = ZoneInterfaceV16.authorizeOrder.selector;
  }

  /**
   * @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
  ) external override returns (bytes4 validOrderMagicValue) {
    if (msg.sender != SEAPORT) {
      // Revert if the caller is not Seaport.
      revert CallerNotSeaport();
    }

    // Set the transfer status of the tokens to false.
    _setTransferStatus(zoneParameters, false);

    // Return the selector of validateOrder as the magic value.
    validOrderMagicValue = ZoneInterfaceV16.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, ZoneInterfaceV16)
    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);
  }

  /**
   * @dev Sets the transfer status of the token based on the consideration
   *      items or offer items.
   *
   * @param zoneParameters The zone parameters.
   * @param active The transfer status of the token.
   */
  function _setTransferStatus(ZoneParameters calldata zoneParameters, bool active) internal {
    uint8 subStandardVersionByte = uint8(bytes1(zoneParameters.extraData[93]));

    if (subStandardVersionByte < 2) {
      return;
    }

    address registry = address(bytes20(zoneParameters.extraData[126:146]));

    address token;
    uint256 identifier;
    uint256 amount;

    if (uint256(zoneParameters.consideration[0].itemType) > 1) {
      // Call on first consideration
      token = zoneParameters.consideration[0].token;
      identifier = zoneParameters.consideration[0].identifier;
      amount = zoneParameters.consideration[0].amount;
    } else {
      // Call on first offer
      token = zoneParameters.offer[0].token;
      identifier = zoneParameters.offer[0].identifier;
      amount = zoneParameters.offer[0].amount;
    }

    if (subStandardVersionByte == 7) {
      address operator = address(bytes20(zoneParameters.extraData[146:166]));
      if (active) {
        IAuthorizedTransferSecurityRegistry(registry).beforeAuthorizedTransfer(operator, token);
      } else {
        IAuthorizedTransferSecurityRegistry(registry).afterAuthorizedTransfer(token);
      }
    } else if (subStandardVersionByte == 8) {
      if (active) {
        IAuthorizedTransferSecurityRegistry(registry).beforeAuthorizedTransfer(token, identifier);
      } else {
        IAuthorizedTransferSecurityRegistry(registry).afterAuthorizedTransfer(token, identifier);
      }
    }
    /* subStandardVersionByte == 9 */
    else {
      if (active) {
        IAuthorizedTransferSecurityRegistry(registry).beforeAuthorizedTransferWithAmount(
          token,
          identifier,
          amount
        );
      } else {
        IAuthorizedTransferSecurityRegistry(registry).afterAuthorizedTransferWithAmount(
          token,
          identifier
        );
      }
    }
  }

  /**
   * @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's active status to true.
    _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. Note that the array of
   *         active signers could grow to a size that this function could not
   *         return, the array of active signers is  expected to be small,
   *         and is managed by the controller.
   *
   * @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 if the given address is an active signer for the zone.
   *
   * @param signer The address to check if it is an active signer.
   *
   * @return The address is an active signer, false otherwise.
   */
  function _isActiveSigner(address signer) internal view returns (bool) {
    // Return the active status of the caller.
    return _signers[signer];
  }

  /**
   * @notice Returns whether the interface is supported.
   *
   * @param interfaceId The interface id to check against.
   */
  function _supportsInterface(bytes4 interfaceId) internal pure returns (bool) {
    // Determine if the interface is supported.
    return (interfaceId == type(SIP5Interface).interfaceId || // SIP-5
      interfaceId == type(ZoneInterfaceV16).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 Internal 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 _assertValidSubstandardAndGetExpectedFulfiller(
    bytes32 orderHash
  ) internal pure returns (address expectedFulfiller) {
    // Revert if the expected fulfiller is not the zero address and does
    // not match the actual fulfiller or if the expected received
    // identifier does not match the actual received identifier.
    assembly {
      // Get the actual fulfiller.
      let actualFulfiller := calldataload(Zone_parameters_fulfiller_cdPtr)
      let extraDataPtr := calldataload(Zone_extraData_cdPtr)
      let considerationPtr := calldataload(Zone_consideration_head_cdPtr)

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

      // Get the actual received identifier.
      let actualReceivedIdentifier := calldataload(
        add(actualReceivedIdentifier_offset, considerationPtr)
      )

      // Get the expected received identifier.
      let expectedReceivedIdentifier := calldataload(
        add(expectedReceivedIdentifier_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)
      }

      // Revert if expected received item does not match the actual
      // received item.
      if iszero(eq(expectedReceivedIdentifier, actualReceivedIdentifier)) {
        // Store left-padded selector with push4, mem[28:32] = selector
        mstore(0, InvalidReceivedItem_error_selector)
        mstore(InvalidReceivedItem_error_expectedReceivedItem_ptr, expectedReceivedIdentifier)
        mstore(InvalidReceivedItem_error_actualReceivedItem_ptr, actualReceivedIdentifier)
        mstore(InvalidReceivedItem_error_orderHash_ptr, orderHash)
        // revert(abi.encodeWithSignature(
        //     "InvalidReceivedItem(uint256,uint256,bytes32)",
        //     expectedReceivedIdentifier,
        //     actualReceievedIdentifier,
        //     orderHash
        // ))
        revert(0x1c, InvalidReceivedItem_error_length)
      }
    }
  }
}

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

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

interface ZoneInterfaceV16 {
  function authorizeOrder(
    ZoneParameters calldata zoneParameters
  ) external returns (bytes4 authorizeOrderMagicValue);

  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 9 : 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 9 : 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 9 : IAuthorizedTransferSecurityRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

enum ListTypes {
  AuthorizerList,
  OperatorList
}

/// @title IAuthorizedTransferSecurityRegistry
/// @dev Interface for the Authorized Transfer Security Registry, a simplified version of the Transfer
///      Security Registry that only supports authorizers and whitelisted operators, and assumes a
///      security level of OperatorWhitelistEnableOTC + authorizers for all collections that use it.
///      Note that a number of view functions on collections that add this validator will not work.
interface IAuthorizedTransferSecurityRegistry {
  event CreatedList(uint256 indexed id, string name);
  event AppliedListToCollection(address indexed collection, uint120 indexed id);
  event ReassignedListOwnership(uint256 indexed id, address indexed newOwner);
  event AddedAccountToList(ListTypes indexed kind, uint256 indexed id, address indexed account);
  event RemovedAccountFromList(ListTypes indexed kind, uint256 indexed id, address indexed account);

  error AuthorizedTransferSecurityRegistry__ListDoesNotExist();
  error AuthorizedTransferSecurityRegistry__CallerDoesNotOwnList();
  error AuthorizedTransferSecurityRegistry__ArrayLengthCannotBeZero();
  error AuthorizedTransferSecurityRegistry__CallerMustHaveElevatedPermissionsForSpecifiedNFT();
  error AuthorizedTransferSecurityRegistry__ListOwnershipCannotBeTransferredToZeroAddress();
  error AuthorizedTransferSecurityRegistry__ZeroAddressNotAllowed();
  error AuthorizedTransferSecurityRegistry__UnauthorizedTransfer();
  error AuthorizedTransferSecurityRegistry__CallerIsNotValidAuthorizer();

  /// Manage lists of authorizers & operators that can be applied to collections
  function createList(string calldata name) external returns (uint120);
  function createListCopy(string calldata name, uint120 sourceListId) external returns (uint120);
  function reassignOwnershipOfList(uint120 id, address newOwner) external;
  function renounceOwnershipOfList(uint120 id) external;
  function applyListToCollection(address collection, uint120 id) external;
  function listOwners(uint120 id) external view returns (address);

  /// Manage and query for authorizers on lists
  function addAuthorizers(uint120 id, address[] calldata accounts) external;
  function removeAuthorizers(uint120 id, address[] calldata accounts) external;
  function getAuthorizers(uint120 id) external view returns (address[] memory);
  function isAuthorizer(uint120 id, address account) external view returns (bool);
  function getAuthorizersByCollection(address collection) external view returns (address[] memory);
  function isAuthorizerByCollection(
    address collection,
    address account
  ) external view returns (bool);

  /// Manage and query for operators on lists
  function addOperators(uint120 id, address[] calldata accounts) external;
  function removeOperators(uint120 id, address[] calldata accounts) external;
  function getOperators(uint120 id) external view returns (address[] memory);
  function isOperator(uint120 id, address account) external view returns (bool);
  function getOperatorsByCollection(address collection) external view returns (address[] memory);
  function isOperatorByCollection(address collection, address account) external view returns (bool);

  /// Ensure that a specific operator has been authorized to transfer tokens
  function validateTransfer(address caller, address from, address to) external view;

  /// Ensure that a transfer has been authorized for a specific tokenId
  function validateTransfer(
    address caller,
    address from,
    address to,
    uint256 tokenId
  ) external view;

  /// Ensure that a transfer has been authorized for a specific amount of a specific tokenId, and
  /// reduce the transferable amount remaining
  function validateTransfer(
    address caller,
    address from,
    address to,
    uint256 tokenId,
    uint256 amount
  ) external;

  /// Legacy alias for validateTransfer (address caller, address from, address to)
  function applyCollectionTransferPolicy(address caller, address from, address to) external view;

  /// Temporarily assign a specific allowed operator for a given collection
  function beforeAuthorizedTransfer(address operator, address token) external;

  /// Clear assignment of a specific allowed operator for a given collection
  function afterAuthorizedTransfer(address token) external;

  /// Temporarily allow a specific tokenId from a given collection to be transferred
  function beforeAuthorizedTransfer(address token, uint256 tokenId) external;

  /// Clear assignment of an specific tokenId's transfer allowance
  function afterAuthorizedTransfer(address token, uint256 tokenId) external;

  /// Temporarily allow a specific amount of a specific tokenId from a given collection to be transferred
  function beforeAuthorizedTransferWithAmount(
    address token,
    uint256 tokenId,
    uint256 amount
  ) external;

  /// Clear assignment of a tokenId's transfer allowance for a specific amount
  function afterAuthorizedTransferWithAmount(address token, uint256 tokenId) external;
}

File 6 of 9 : 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 7 of 9 : SignedZoneV16RoyaltyEventsAndErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

/**
 * @notice SignedZoneV16RoyaltyEventsAndErrors contains errors and events
 *         related to zone interaction.
 */
interface SignedZoneV16RoyaltyEventsAndErrors {
  /**
   * @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 when the signature has expired.
   */
  error SignatureExpired(uint256 expiration, bytes32 orderHash);

  /**
   * @dev Revert with an error when the caller is not seaport.
   */
  error CallerNotSeaport();

  /**
   * @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 received item does not match.
   */
  error InvalidReceivedItem(
    uint256 expectedReceivedIdentifier,
    uint256 actualReceievedIdentifier,
    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);

  /**
   * @dev Revert when an unsupported function selector is found.
   */
  error UnsupportedFunctionSelector();
}

File 8 of 9 : 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 9 of 9 : SignedZoneV16RoyaltyConstants.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
);

// @dev Function selectors used in the fallback function..
bytes4 constant UPDATE_SIGNER_SELECTOR = 0xf460590b;
bytes4 constant GET_ACTIVE_SIGNERS_SELECTOR = 0xa784b80c;
bytes4 constant IS_ACTIVE_SIGNER_SELECTOR = 0x7dff5a79;
bytes4 constant SUPPORTS_INTERFACE_SELECTOR = 0x01ffc9a7;

/*
 *  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 InvalidReceivedItem(uint256 expectedReceivedIdentifier, uint256 actualReceievedIdentifier, bytes32 orderHash)
 *    - Defined in SignedZoneEventsAndErrors.sol
 *  Memory layout:
 *    - 0x00: Left-padded selector (data begins at 0x1c)
 *    - 0x20: expectedReceivedIdentifier
 *    - 0x40: actualReceievedIdentifier
 *    - 0x60: orderHash
 * Revert buffer is memory[0x1c:0x80]
 */
uint256 constant InvalidReceivedItem_error_selector = 0xb36c03e8;
uint256 constant InvalidReceivedItem_error_expectedReceivedItem_ptr = 0x20;
uint256 constant InvalidReceivedItem_error_actualReceivedItem_ptr = 0x40;
uint256 constant InvalidReceivedItem_error_orderHash_ptr = 0x60;
uint256 constant InvalidReceivedItem_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_expected_length_substandard_1 = 0x7e; // 126
uint256 constant InvalidExtraDataLength_expected_length_substandard_7 = 0xa6; // 166
uint256 constant InvalidExtraDataLength_expected_length_substandard_8_or_9 = 0x92; // 146

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;

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

// 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 actualReceivedIdentifier_offset = 0x84;
uint256 constant expectedReceivedIdentifier_offset = 0xa2;

// Spent Item Size
uint256 constant SpentItem_size = 0x80;

// Received Item Size
uint256 constant ReceivedItem_size = 0xa0;

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"zoneName","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerNotSeaport","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":"uint256","name":"expectedReceivedIdentifier","type":"uint256"},{"internalType":"uint256","name":"actualReceievedIdentifier","type":"uint256"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"InvalidReceivedItem","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":[{"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"},{"inputs":[],"name":"UnsupportedFunctionSelector","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":"nonpayable","type":"fallback"},{"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":"authorizeOrder","outputs":[{"internalType":"bytes4","name":"authorizedOrderMagicValue","type":"bytes4"}],"stateMutability":"nonpayable","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":"nonpayable","type":"function"}]

610180604052346200008f576200001f620000196200010c565b620001ef565b6040516114889081620004318239608051818181610e4701528181610f3401526110e6015260a05181611371015260c05181611395015260e0518161134e015261010051816111fc015261012051816112fb01526101405181611322015261016051818181607701526103640152f35b600080fd5b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b03821190821017620000cf57604052565b620000d962000094565b604052565b6020906001600160401b038111620000fc575b601f01601f19160190565b6200010662000094565b620000f1565b620018b9908138038060405193620001258286620000ab565b8439820160209283818303126200008f578051906001600160401b0382116200008f57019281601f850112156200008f5783516200016381620000de565b92620001736040519485620000ab565b8184528282870101116200008f5760005b8181106200019a57508260009394955001015290565b858101830151848201840152820162000184565b60408051919082016001600160401b03811183821017620001df575b60405260038252620322e360ec1b6020830152565b620001e962000094565b620001ca565b620001f9620001ae565b6020815191012060c0526040516020810181620002c3620002b66200028d62000271620002566200023e87600d906c08a92a06e626488dedac2d2dc5609b1b81520190565b6b1cdd1c9a5b99c81b985b594b60a21b8152600c0190565b6e1cdd1c9a5b99c81d995c9cda5bdb8b608a1b8152600f0190565b6f1d5a5b9d0c8d4d8818da185a5b92590b60821b815260100190565b7f6164647265737320766572696679696e67436f6e747261637400000000000000815260190190565b602960f81b815260010190565b0391620002d9601f1993848101835282620000ab565b51902060e0526040516200039e60208201928262000391620002b6620003786200035a6200033c6200031e8a600c906b0a6d2cedccac89ee4c8cae4560a31b81520190565b711859191c995cdcc8199d5b199a5b1b195c8b60721b815260120190565b711d5a5b9d0d8d08195e1c1a5c985d1a5bdb8b60721b815260120190565b71189e5d195ccccc881bdc99195c92185cda0b60721b815260120190565b6c189e5d195cc818dbdb9d195e1d609a1b8152600d0190565b03908101835282620000ab565b5190206101005246610120526c68f116a894984e2db1123eb39561016052336080526020815191012060a0526200040560e0519060a0519160c0516040519360805192600052602052604052466060523060805260a0600020926040526000606052608052565b610140527f98a7ac23945182ac62b68fbe5ba35cc0bf5c4c34b3a410ce94a4c2270282d6b5600080a156fe60806040526004361015610028575b346100235761001b6106e0565b602081519101f35b600080fd5b6000803560e01c90816301e4d72a146100675750806317b1f9421461005e57632e778efc0361000e57610059610499565b61000e565b50610059610353565b3461031d5761007536610320565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361030c576100ad6113d0565b6100ba60a08201826107d9565b929082359360c43591602491607e84840135106102fc57604484013560f81c6102ec5760a184013560f81c9360078510600186111660098611176102dc579060598892013560c01c924284106102c75760a435850135156102725761011e836113ea565b946101298383610549565b9890976002811015610209575050509361018e9695936101809361015361015c946101889861057c565b929092936111db565b6101646112f6565b61190160f01b6000526002526022526042600020906000602252565b923691610837565b90611270565b6101bb6101b76101b08360018060a01b03166000526000602052604060002090565b5460ff1690565b1590565b6101dd576101c882610a2b565b60405162f26b9560e11b8152602090f35b0390f35b6040516317c3008960e01b81526001600160a01b03919091166004820152602481019290925250604490fd5b60079192939495501460001461024d5760a6841061023e5750506101889361018e969593896101536101809561015c9561056b565b63d232fd2c8a9152602052601cfd5b6092841061023e5750506101889361018e969593896101536101809561015c9561055a565b82632be76224885260606020526001604052606052602a6080527f436f6e73696465726174696f6e206d7573742068617665206174206c6561737460a052691037b7329034ba32b69760b11b60c05260c4601cfd5b8284631654607189526020526040526044601cfd5b838863267879998852602052601cfd5b828763641157748752602052601cfd5b828763d232fd2c8752602052601cfd5b6304bcd3dd60e51b60805260046080fd5b80fd5b60031990602081830112610023576004359167ffffffffffffffff83116100235782610140920301126100235760040190565b50346100235761036236610320565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036103ad5761039b90610c88565b604051630bd8fca160e11b8152602090f35b6040516304bcd3dd60e51b8152600490fd5b600091031261002357565b60005b8381106103dd5750506000910152565b81810151838201526020016103cd565b90602091610406815180928185528580860191016103ca565b601f01601f1916010190565b610424604092838352838301906103ed565b906020908181840391015283519182815281810182808560051b8401019601946000925b858410610459575050505050505090565b909192939495968580610488600193601f1986820301885286838d5180518452015191818582015201906103ed565b990194019401929594939190610448565b50346100235760008060031936011261031d5760408051916104ba83610625565b60018352805b6020808210156104ed578351602092916104d982610625565b8482526060818301528287010152016104c0565b846105316101d9866007610500856108ac565b515261052361050d6110bf565b90869894939895929551958694602086016108c6565b03601f198101835282610662565b602061053c866108ac565b5101525192839283610412565b90605d1161002357601d0190604090565b9060921161002357605d0190603590565b9060a61161002357605d0190604990565b90607e1161002357605d0190602190565b91909182600411610023578211610023576004916003190190565b91909182602411610023578211610023576024916023190190565b9060921161002357607e0190601490565b9060a6116100235760920190601490565b6001600160a01b0381160361002357565b90816020910312610023573561060b816105e5565b90565b50634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761064157604052565b61064961060e565b604052565b67ffffffffffffffff811161064157604052565b90601f8019910116810190811067ffffffffffffffff82111761064157604052565b6020908160408183019282815285518094520193019160005b8281106106ab575050505090565b83516001600160a01b03168552938101939281019260010161069d565b90816020910312610023573580151581036100235790565b6060906000356001600160e01b03191663f460590b60e01b8103610743575061074161072661071a610712363661058d565b8101906105f6565b6001600160a01b031690565b61073b61073336366105a8565b8101906106c8565b90610e44565b565b9091506329e12e0360e21b8103610772575061052361060b610763610f18565b60405192839160208301610684565b637dff5a7960e01b036107cb5761052361060b6107b661079861071a610712363661058d565b6001600160a01b031660009081526020819052604090205460ff1690565b60408051911515602083015290928391820190565b6354c91b876000526004601cfd5b903590601e1981360301821215610023570180359067ffffffffffffffff82116100235760200191813603831361002357565b60209067ffffffffffffffff811161082a575b601f01601f19160190565b61083261060e565b61081f565b9291926108438261080c565b916108516040519384610662565b829481845281830111610023578281602093846000960137010152565b60209067ffffffffffffffff8111610888575b60051b0190565b61089061060e565b610881565b50634e487b7160e01b600052603260045260246000fd5b6020908051156108ba570190565b6108c2610895565b0190565b909493919481526108e360209560808784015260808301906103ed565b818103604083015285808551928381520194019060005b8181106109175750505061060b93945060608184039101526103ed565b8251865294870194918701916001016108fa565b605d918210156108ba570190565b6bffffffffffffffffffffffff19903581811693926014811061095b57505050565b60140360031b82901b16169150565b903590601e1981360301821215610023570180359067ffffffffffffffff8211610023576020019160a082023603831361002357565b90156109a95790565b61060b610895565b600611156109bb57565b634e487b7160e01b600052602160045260246000fd5b3560068110156100235790565b903590601e1981360301821215610023570180359067ffffffffffffffff821161002357602001918160071b3603831361002357565b3561060b816105e5565b506040513d6000823e3d90fd5b60a081019060ff610a5f610a59610a4b610a4586866107d9565b9061092b565b356001600160f81b03191690565b60f81c90565b169160028310610c8357610a8e610a88610a82610a7c84866107d9565b906105c3565b90610939565b60601c90565b91608081016001610ab0610aab610aa5848661096a565b906109a0565b6109d1565b610ab9816109b1565b1115610c4357610ad76020610ad1610aa5848661096a565b01610a14565b946060610af8610aa56040610aef610aa5878961096a565b0135948661096a565b0135905b60078103610b9757505050610a82610b1a610b2093610a88936107d9565b906105d4565b6001600160a01b0390911691823b1561002357604051635079331560e01b81526001600160a01b03928316600482015291166024820152906000908290818381604481015b03925af18015610b8a575b610b775750565b80610b846107419261064e565b806103bf565b610b92610a1e565b610b70565b91959493509150600803610beb57506001600160a01b031691823b15610023576040516301d0718b60e51b81526001600160a01b039092166004830152602482015290600090829081838160448101610b65565b906001600160a01b0316803b15610023576040516328cc113160e01b81526001600160a01b0393909316600484015260248301939093526044820152906000908290606490829084905af18015610b8a57610b775750565b5060608101610c5a6020610ad1610aa584866109de565b946060610c7b610aa56040610c72610aa587896109de565b013594866109de565b013590610afc565b505050565b60a081019060ff610ca2610a59610a4b610a4586866107d9565b169160028310610c8357610cbf610a88610a82610a7c84866107d9565b91608081016001610cd6610aab610aa5848661096a565b610cdf816109b1565b1115610e0857610cf76020610ad1610aa5848661096a565b94610d16610aa56040610d0d610aa5868861096a565b0135938561096a565b505b60078103610d6f575050610d2f91610b1a916107d9565b50506001600160a01b0316803b1561002357604051630ad3889960e01b81526001600160a01b039092166004830152600090829081838160248101610b65565b9094939250600814159050610dc3576001600160a01b031691823b156100235760405163b89c4b0d60e01b81526001600160a01b039092166004830152602482015290600090829081838160448101610b65565b6001600160a01b031691823b156100235760405163b6e39ba160e01b81526001600160a01b039092166004830152602482015290600090829081838160448101610b65565b5060608101610e1f6020610ad1610aa584866109de565b94610e3e610aa56040610e35610aa586886109de565b013593856109de565b50610d18565b907f00000000000000000000000000000000000000000000000000000000000000003303610f0a5715610ebf576001600160a01b031660008181526020818152604091829020805460ff1916600117905590519182527f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f2491a1565b6001600160a01b031660008181526020818152604091829020805460ff1916905590519182527f3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b91a1565b636d5769be6000526004601cfd5b6040516366a2489f60e01b8152306004820152600080826024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa918215611012575b8192610f7157505090565b9091503d8083833e610f838183610662565b8101602091828183031261100a5780519067ffffffffffffffff821161100e570181601f8201121561100a57805190610fbb8261086e565b94610fc96040519687610662565b828652848087019360051b83010193841161031d57508301905b828210610ff1575050505090565b8380918351610fff816105e5565b815201910190610fe3565b8380fd5b8480fd5b61101a610a1e565b610f66565b81601f820112156100235780516110358161080c565b926110436040519485610662565b818452602082840101116100235761060b91602080850191016103ca565b81601f82011215610023578051916110788361086e565b926110866040519485610662565b808452602092838086019260051b820101928311610023578301905b8282106110b0575050505090565b815181529083019083016110a2565b6110c76112f6565b604051628f139360e31b815230600482015290919060009081816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9182156111ce575b8092819282809261112c575b505090919293565b9350935050503d8082843e6111418184610662565b820160a0838203126111ca5760208301519067ffffffffffffffff9182811161100a578161117091860161101f565b91604085015181811161100e578261118991870161101f565b9460608101518281116111c657836111a2918301611061565b94608082015192831161031d57506111bb92910161101f565b909291903880611124565b8580fd5b5080fd5b6111d6610a1e565b611118565b93926111ea9192933691610837565b602081519101206040519260208401947f0000000000000000000000000000000000000000000000000000000000000000865260018060a01b0316604085015267ffffffffffffffff8093166060850152608084015260a083015260a0825260c082019082821090821117611263575b60405251902090565b61126b61060e565b61125a565b9190916000926000918280528151601f1983019283518260410394600186111561129e575b50505050505050565b90919293949596975060408301948551966060850151891a906112dc575b8452815260208760808360015afa50525252519038808080808080611295565b506001600160ff1b038716865260ff87901c601b016112bc565b6000467f00000000000000000000000000000000000000000000000000000000000000000361134457507f000000000000000000000000000000000000000000000000000000000000000090565b60405190608051907f000000000000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006020527f0000000000000000000000000000000000000000000000000000000000000000604052466060523060805260a081209260405260605260805290565b6020600435036113dc57565b6346d5d8956000526004601cfd5b906044359160c435806045013560601c9360a435608401359160a20135908086141586151516611438575081810361142157505050565b63b36c03e86000526020526040526060526064601cfd5b839086631bcf9bb76000526020526040526060526064601cfdfea26469706673582212203fc511b7c1ba46250e07db13f3f1c82c4236ab39a74023885f681960425a7e3d64736f6c6343000811003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012526f79616c7479456e666f7263656d656e740000000000000000000000000000

Deployed Bytecode

0x60806040526004361015610028575b346100235761001b6106e0565b602081519101f35b600080fd5b6000803560e01c90816301e4d72a146100675750806317b1f9421461005e57632e778efc0361000e57610059610499565b61000e565b50610059610353565b3461031d5761007536610320565b7f0000000000000000000000000000000000000068f116a894984e2db1123eb3956001600160a01b0316330361030c576100ad6113d0565b6100ba60a08201826107d9565b929082359360c43591602491607e84840135106102fc57604484013560f81c6102ec5760a184013560f81c9360078510600186111660098611176102dc579060598892013560c01c924284106102c75760a435850135156102725761011e836113ea565b946101298383610549565b9890976002811015610209575050509361018e9695936101809361015361015c946101889861057c565b929092936111db565b6101646112f6565b61190160f01b6000526002526022526042600020906000602252565b923691610837565b90611270565b6101bb6101b76101b08360018060a01b03166000526000602052604060002090565b5460ff1690565b1590565b6101dd576101c882610a2b565b60405162f26b9560e11b8152602090f35b0390f35b6040516317c3008960e01b81526001600160a01b03919091166004820152602481019290925250604490fd5b60079192939495501460001461024d5760a6841061023e5750506101889361018e969593896101536101809561015c9561056b565b63d232fd2c8a9152602052601cfd5b6092841061023e5750506101889361018e969593896101536101809561015c9561055a565b82632be76224885260606020526001604052606052602a6080527f436f6e73696465726174696f6e206d7573742068617665206174206c6561737460a052691037b7329034ba32b69760b11b60c05260c4601cfd5b8284631654607189526020526040526044601cfd5b838863267879998852602052601cfd5b828763641157748752602052601cfd5b828763d232fd2c8752602052601cfd5b6304bcd3dd60e51b60805260046080fd5b80fd5b60031990602081830112610023576004359167ffffffffffffffff83116100235782610140920301126100235760040190565b50346100235761036236610320565b7f0000000000000000000000000000000000000068f116a894984e2db1123eb3956001600160a01b031633036103ad5761039b90610c88565b604051630bd8fca160e11b8152602090f35b6040516304bcd3dd60e51b8152600490fd5b600091031261002357565b60005b8381106103dd5750506000910152565b81810151838201526020016103cd565b90602091610406815180928185528580860191016103ca565b601f01601f1916010190565b610424604092838352838301906103ed565b906020908181840391015283519182815281810182808560051b8401019601946000925b858410610459575050505050505090565b909192939495968580610488600193601f1986820301885286838d5180518452015191818582015201906103ed565b990194019401929594939190610448565b50346100235760008060031936011261031d5760408051916104ba83610625565b60018352805b6020808210156104ed578351602092916104d982610625565b8482526060818301528287010152016104c0565b846105316101d9866007610500856108ac565b515261052361050d6110bf565b90869894939895929551958694602086016108c6565b03601f198101835282610662565b602061053c866108ac565b5101525192839283610412565b90605d1161002357601d0190604090565b9060921161002357605d0190603590565b9060a61161002357605d0190604990565b90607e1161002357605d0190602190565b91909182600411610023578211610023576004916003190190565b91909182602411610023578211610023576024916023190190565b9060921161002357607e0190601490565b9060a6116100235760920190601490565b6001600160a01b0381160361002357565b90816020910312610023573561060b816105e5565b90565b50634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761064157604052565b61064961060e565b604052565b67ffffffffffffffff811161064157604052565b90601f8019910116810190811067ffffffffffffffff82111761064157604052565b6020908160408183019282815285518094520193019160005b8281106106ab575050505090565b83516001600160a01b03168552938101939281019260010161069d565b90816020910312610023573580151581036100235790565b6060906000356001600160e01b03191663f460590b60e01b8103610743575061074161072661071a610712363661058d565b8101906105f6565b6001600160a01b031690565b61073b61073336366105a8565b8101906106c8565b90610e44565b565b9091506329e12e0360e21b8103610772575061052361060b610763610f18565b60405192839160208301610684565b637dff5a7960e01b036107cb5761052361060b6107b661079861071a610712363661058d565b6001600160a01b031660009081526020819052604090205460ff1690565b60408051911515602083015290928391820190565b6354c91b876000526004601cfd5b903590601e1981360301821215610023570180359067ffffffffffffffff82116100235760200191813603831361002357565b60209067ffffffffffffffff811161082a575b601f01601f19160190565b61083261060e565b61081f565b9291926108438261080c565b916108516040519384610662565b829481845281830111610023578281602093846000960137010152565b60209067ffffffffffffffff8111610888575b60051b0190565b61089061060e565b610881565b50634e487b7160e01b600052603260045260246000fd5b6020908051156108ba570190565b6108c2610895565b0190565b909493919481526108e360209560808784015260808301906103ed565b818103604083015285808551928381520194019060005b8181106109175750505061060b93945060608184039101526103ed565b8251865294870194918701916001016108fa565b605d918210156108ba570190565b6bffffffffffffffffffffffff19903581811693926014811061095b57505050565b60140360031b82901b16169150565b903590601e1981360301821215610023570180359067ffffffffffffffff8211610023576020019160a082023603831361002357565b90156109a95790565b61060b610895565b600611156109bb57565b634e487b7160e01b600052602160045260246000fd5b3560068110156100235790565b903590601e1981360301821215610023570180359067ffffffffffffffff821161002357602001918160071b3603831361002357565b3561060b816105e5565b506040513d6000823e3d90fd5b60a081019060ff610a5f610a59610a4b610a4586866107d9565b9061092b565b356001600160f81b03191690565b60f81c90565b169160028310610c8357610a8e610a88610a82610a7c84866107d9565b906105c3565b90610939565b60601c90565b91608081016001610ab0610aab610aa5848661096a565b906109a0565b6109d1565b610ab9816109b1565b1115610c4357610ad76020610ad1610aa5848661096a565b01610a14565b946060610af8610aa56040610aef610aa5878961096a565b0135948661096a565b0135905b60078103610b9757505050610a82610b1a610b2093610a88936107d9565b906105d4565b6001600160a01b0390911691823b1561002357604051635079331560e01b81526001600160a01b03928316600482015291166024820152906000908290818381604481015b03925af18015610b8a575b610b775750565b80610b846107419261064e565b806103bf565b610b92610a1e565b610b70565b91959493509150600803610beb57506001600160a01b031691823b15610023576040516301d0718b60e51b81526001600160a01b039092166004830152602482015290600090829081838160448101610b65565b906001600160a01b0316803b15610023576040516328cc113160e01b81526001600160a01b0393909316600484015260248301939093526044820152906000908290606490829084905af18015610b8a57610b775750565b5060608101610c5a6020610ad1610aa584866109de565b946060610c7b610aa56040610c72610aa587896109de565b013594866109de565b013590610afc565b505050565b60a081019060ff610ca2610a59610a4b610a4586866107d9565b169160028310610c8357610cbf610a88610a82610a7c84866107d9565b91608081016001610cd6610aab610aa5848661096a565b610cdf816109b1565b1115610e0857610cf76020610ad1610aa5848661096a565b94610d16610aa56040610d0d610aa5868861096a565b0135938561096a565b505b60078103610d6f575050610d2f91610b1a916107d9565b50506001600160a01b0316803b1561002357604051630ad3889960e01b81526001600160a01b039092166004830152600090829081838160248101610b65565b9094939250600814159050610dc3576001600160a01b031691823b156100235760405163b89c4b0d60e01b81526001600160a01b039092166004830152602482015290600090829081838160448101610b65565b6001600160a01b031691823b156100235760405163b6e39ba160e01b81526001600160a01b039092166004830152602482015290600090829081838160448101610b65565b5060608101610e1f6020610ad1610aa584866109de565b94610e3e610aa56040610e35610aa586886109de565b013593856109de565b50610d18565b907f0000000000000000000000008001507b20bfa9408c0902b75a103129ed6703203303610f0a5715610ebf576001600160a01b031660008181526020818152604091829020805460ff1916600117905590519182527f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f2491a1565b6001600160a01b031660008181526020818152604091829020805460ff1916905590519182527f3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b91a1565b636d5769be6000526004601cfd5b6040516366a2489f60e01b8152306004820152600080826024817f0000000000000000000000008001507b20bfa9408c0902b75a103129ed6703206001600160a01b03165afa918215611012575b8192610f7157505090565b9091503d8083833e610f838183610662565b8101602091828183031261100a5780519067ffffffffffffffff821161100e570181601f8201121561100a57805190610fbb8261086e565b94610fc96040519687610662565b828652848087019360051b83010193841161031d57508301905b828210610ff1575050505090565b8380918351610fff816105e5565b815201910190610fe3565b8380fd5b8480fd5b61101a610a1e565b610f66565b81601f820112156100235780516110358161080c565b926110436040519485610662565b818452602082840101116100235761060b91602080850191016103ca565b81601f82011215610023578051916110788361086e565b926110866040519485610662565b808452602092838086019260051b820101928311610023578301905b8282106110b0575050505090565b815181529083019083016110a2565b6110c76112f6565b604051628f139360e31b815230600482015290919060009081816024817f0000000000000000000000008001507b20bfa9408c0902b75a103129ed6703206001600160a01b03165afa9182156111ce575b8092819282809261112c575b505090919293565b9350935050503d8082843e6111418184610662565b820160a0838203126111ca5760208301519067ffffffffffffffff9182811161100a578161117091860161101f565b91604085015181811161100e578261118991870161101f565b9460608101518281116111c657836111a2918301611061565b94608082015192831161031d57506111bb92910161101f565b909291903880611124565b8580fd5b5080fd5b6111d6610a1e565b611118565b93926111ea9192933691610837565b602081519101206040519260208401947f58d1345cbd7d0ceb38b86441d42a4086bc412b7f1ed7d947a569ed7d68b1b790865260018060a01b0316604085015267ffffffffffffffff8093166060850152608084015260a083015260a0825260c082019082821090821117611263575b60405251902090565b61126b61060e565b61125a565b9190916000926000918280528151601f1983019283518260410394600186111561129e575b50505050505050565b90919293949596975060408301948551966060850151891a906112dc575b8452815260208760808360015afa50525252519038808080808080611295565b506001600160ff1b038716865260ff87901c601b016112bc565b6000467f00000000000000000000000000000000000000000000000000000000000081730361134457507f9f01268e78945b80c2fd71b7b27f9801018fb4f934a157fa947922a172a7f36190565b60405190608051907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f970c5baece800861db26e88cd0a8a8ae7669d63d9b73f2dfafea8cb3551451b16020527f88f72b566ae0c96f6fffac4bc8ac74909f61512ac0c06a8124d5ed420d306f90604052466060523060805260a081209260405260605260805290565b6020600435036113dc57565b6346d5d8956000526004601cfd5b906044359160c435806045013560601c9360a435608401359160a20135908086141586151516611438575081810361142157505050565b63b36c03e86000526020526040526060526064601cfd5b839086631bcf9bb76000526020526040526060526064601cfdfea26469706673582212203fc511b7c1ba46250e07db13f3f1c82c4236ab39a74023885f681960425a7e3d64736f6c63430008110033

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

00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012526f79616c7479456e666f7263656d656e740000000000000000000000000000

-----Decoded View---------------
Arg [0] : zoneName (string): RoyaltyEnforcement

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [2] : 526f79616c7479456e666f7263656d656e740000000000000000000000000000


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
[ 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.