ETH Price: $3,473.16 (+4.18%)
Gas: 5.6 Gwei

Token

Early Retired Cats Club (ERCC)
 

Overview

Max Total Supply

1,930 ERCC

Holders

691

Market

Volume (24H)

0.2861 ETH

Min Price (24H)

$468.88 @ 0.135000 ETH

Max Price (24H)

$524.79 @ 0.151100 ETH
Balance
1 ERCC
0xE31235BC3880EB1fBb4c53FD7d882D2F5CBE56f3
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Cuteness crawling up your hooman soul. Ever seen Meows this cute? Explore the world of 1,930 Cats with ERCC.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
ChainLinkNeowizERC721

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 36 : ChainLinkNeowizERC721.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "./libs/@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./libs/@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "./libs/@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "./NeowizERC721.sol";

contract ChainLinkNeowizERC721 is VRFConsumerBaseV2, NeowizERC721 {
    uint64 public subscriptionId;
    VRFCoordinatorV2Interface public COORDINATOR;

    /// @param _name The name of the token
    /// @param _symbol The symbol of the token
    /// @param _maxTotalSupply The max token amount allowed to mint regardless of how many tokens are burnt.
    /// @param _teamSupply The token amount reserved for team
    /// @param _team The address to receive tokens in team-minting
    /// @param _payment The address of token to pay when minting. Set zero to use ETH.
    /// @param _unrevealedURI The ipfs uri of metadata before reveal
    /// @param _trustedForwarder The address of ERC2771 forwarder
    /// @param _subscriptionId Your chainlink subscriptionId. Constants from https://docs.chain.link/docs/vrf-contracts/
    /// @param _vrfCoordinator Chainlink vrfCoordinator in the network. See https://docs.chain.link/docs/vrf-contracts/#configurations
    constructor(
        string memory _name,
        string memory _symbol,
        uint256 _maxTotalSupply,
        uint256 _teamSupply,
        address _team,
        address _payment,
        string memory _unrevealedURI,
        address _trustedForwarder,
        uint64 _subscriptionId,
        address _vrfCoordinator,
        SalesInfo memory _salesInfo
    )
        VRFConsumerBaseV2(_vrfCoordinator)
        NeowizERC721(
            _name,
            _symbol,
            _maxTotalSupply,
            _teamSupply,
            _team,
            _payment,
            _unrevealedURI,
            _trustedForwarder,
            _salesInfo
        )
    {
        subscriptionId = _subscriptionId;
        COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator);
    }

    /// @notice Request random number through Chainlink VRF.
    /// @dev   The callback `_setRandomSeed` requires all tokens to be minted.
    /// @param _keyHash Chainlink-provided Key Hash
    /// @param _requestConfirmations Variable number of confirmations
    /// @param _callbackGasLimit Callback function gas limit
    function requestRandomSeed(
        bytes32 _keyHash,
        uint16 _requestConfirmations, // 3
        uint32 _callbackGasLimit // 100000
    ) external whenSoldout onlyOperator {
        COORDINATOR.requestRandomWords(
            _keyHash,
            subscriptionId,
            _requestConfirmations,
            _callbackGasLimit,
            1 // numWords
        );
    }

    function fulfillRandomWords(uint256, /* requestId */ uint256[] memory _randomWords) internal override {
        _setRandomSeed(_randomWords[0]);
    }
}

File 2 of 36 : ERC721WithPermit.sol
//SPDX-License-Identifier: MIT
// Reference: https://github.com/dievardump/erc721-with-permits/blob/main/contracts/ERC721WithPermit.sol
pragma solidity 0.8.23;

import "../libs/@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "../libs/@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import "../libs/@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

import "./IERC721WithPermit.sol";

/// @title ERC721WithPermit
/// @author Simon Fremaux (@dievardump) & William Schwab (@wschwab)
/// @notice This implementation of Permits links the nonce to the tokenId instead of the owner
///         This way, it is possible for a same account to create several usable permits at the same time,
///         for different ids
///
///         This implementation overrides _transfer and increments the nonce linked to a tokenId
///         every time it is transfered
abstract contract ERC721WithPermit is IERC721WithPermit, ERC721 {
    bytes32 public constant PERMIT_TYPEHASH =
        keccak256("Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)");

    mapping(uint256 => uint256) private _nonces;

    // this are saved as immutable for cheap access
    // the chainId is also saved to be able to recompute domainSeparator
    // in the case of a fork
    bytes32 private immutable _domainSeparator;
    uint256 private immutable _domainChainId;

    constructor() {
        uint256 chainId;
        //solhint-disable-next-line no-inline-assembly
        assembly {
            chainId := chainid()
        }

        _domainChainId = chainId;
        _domainSeparator = _calculateDomainSeparator(chainId);
    }

    /// @notice Builds the DOMAIN_SEPARATOR (eip712) at time of use
    /// @dev This is not set as a constant, to ensure that the chainId will change in the event of a chain fork
    /// @return the DOMAIN_SEPARATOR of eip712
    function DOMAIN_SEPARATOR() public view returns (bytes32) {
        uint256 chainId;
        //solhint-disable-next-line no-inline-assembly
        assembly {
            chainId := chainid()
        }

        return (chainId == _domainChainId) ? _domainSeparator : _calculateDomainSeparator(chainId);
    }

    function _calculateDomainSeparator(uint256 chainId) internal view returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name())),
                    keccak256(bytes("1")),
                    chainId,
                    address(this)
                )
            );
    }

    /// @notice Allows to retrieve current nonce for token
    /// @param tokenId token id
    /// @return current token nonce
    function nonces(uint256 tokenId) public view returns (uint256) {
        require(_exists(tokenId), "!UNKNOWN_TOKEN!");
        return _nonces[tokenId];
    }

    /// @notice function to be called by anyone to approve `spender` using a Permit signature
    /// @dev Anyone can call this to approve `spender`, even a third-party
    /* /// @param owner the owner of the token */
    /// @param spender the actor to approve
    /// @param tokenId the token id
    /// @param deadline the deadline for the permit to be used
    /// @param signature permit
    function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory signature) public {
        require(deadline >= block.timestamp, "!PERMIT_DEADLINE_EXPIRED!");

        bytes32 digest = _buildDigest(
            // owner,
            spender,
            tokenId,
            _nonces[tokenId],
            deadline
        );

        (address recoveredAddress, ) = ECDSA.tryRecover(digest, signature);
        require(
            // verify if the recovered address is owner or approved on tokenId
            // and make sure recoveredAddress is not address(0), else getApproved(tokenId) might match
            (recoveredAddress != address(0) && _isApprovedOrOwner(recoveredAddress, tokenId)) ||
                // else try to recover signature using SignatureChecker, which also allows to recover signature made by contracts
                SignatureChecker.isValidSignatureNow(ownerOf(tokenId), digest, signature),
            "!INVALID_PERMIT_SIGNATURE!"
        );

        _approve(spender, tokenId);
    }

    /// @notice Builds the permit digest to sign
    /// @param spender the token spender
    /// @param tokenId the tokenId
    /// @param nonce the nonce to make a permit for
    /// @param deadline the deadline before when the permit can be used
    /// @return the digest (following eip712) to sign
    function _buildDigest(
        address spender,
        uint256 tokenId,
        uint256 nonce,
        uint256 deadline
    ) public view returns (bytes32) {
        return
            ECDSA.toTypedDataHash(
                DOMAIN_SEPARATOR(),
                keccak256(abi.encode(PERMIT_TYPEHASH, spender, tokenId, nonce, deadline))
            );
    }

    /// @dev helper to easily increment a nonce for a given tokenId
    /// @param tokenId the tokenId to increment the nonce for
    function _incrementNonce(uint256 tokenId) internal {
        _nonces[tokenId]++;
    }

    /// @dev _transfer override to be able to increment the nonce
    /// @inheritdoc ERC721
    function _transfer(address from, address to, uint256 tokenId) internal virtual override {
        // increment the nonce to be sure it can't be reused
        _incrementNonce(tokenId);

        // do normal transfer
        super._transfer(from, to, tokenId);
    }

    /// @notice Query if a contract implements an interface
    /// @param interfaceId The interface identifier, as specified in ERC-165
    /// @dev Overriden from ERC721 here in order to include the interface of this EIP
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return
            interfaceId == type(IERC721WithPermit).interfaceId || // 0x5604e225
            super.supportsInterface(interfaceId);
    }
}

File 3 of 36 : IERC721WithPermit.sol
//SPDX-License-Identifier: MIT
// Reference: https://github.com/dievardump/erc721-with-permits/blob/main/contracts/IERC721WithPermit.sol
pragma solidity 0.8.23;

import "../libs/@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "../libs/@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import "../libs/@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

/// @title IERC721WithPermit
/// @author Simon Fremaux (@dievardump) & William Schwab
/// @notice Required interface
interface IERC721WithPermit {
    function DOMAIN_SEPARATOR() external view returns (bytes32);

    /// @notice Allows to retrieve current nonce for token
    /// @param tokenId token id
    /// @return current token nonce
    function nonces(uint256 tokenId) external view returns (uint256);

    /// @notice function to be called by anyone to approve `spender` using a Permit signature
    /// @dev Anyone can call this to approve `spender`, even a third-party
    /// @param spender the actor to approve
    /// @param tokenId the token id
    /// @param deadline the deadline for the permit to be used
    /// @param signature permit
    function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory signature) external;
}

File 4 of 36 : INeowizERC721.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

interface INeowizERC721 {
    event PaymentUpdated(address payment);

    event UnrevealedURIUpdated(string uri);

    event RoundAdded(
        uint256 indexed roundId,
        uint256 state,
        uint256 maxMintPerAccount,
        uint256 maxMint,
        uint256 price,
        bytes32 merkleRoot,
        uint256 startTs,
        uint256 endTs
    );

    event StateUpdated(uint256 indexed roundId, uint256 state);

    event MaxMintUpdated(uint256 indexed roundId, uint256 maxMint);

    event MaxMintPerAccountUpdated(uint256 indexed roundId, uint256 maxMint);

    event PriceUpdated(uint256 indexed roundId, uint256 price);

    event MerkleRootUpdated(uint256 indexed roundId, bytes32 merkleRoot);

    event RoundTimestampUpdated(uint256 indexed roundId, uint256 startTs, uint256 endTs);

    event BaseURIUpdated(string uri);

    event RoyaltyInfoUpdated(address receiver, uint96 feeBasisPoints);

    event Revealed();

    event NewOperator(address operator);

    function isRevealed() external returns (bool);

    function burn(uint256 _tokenId) external;

    function randomSeed() external view returns (uint256);

    function MAX_TOTAL_SUPPLY() external view returns (uint256);

    function TEAM_SUPPLY() external view returns (uint256);
}

File 5 of 36 : VRFCoordinatorV2Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface VRFCoordinatorV2Interface {
  /**
   * @notice Get configuration relevant for making requests
   * @return minimumRequestConfirmations global min for request confirmations
   * @return maxGasLimit global max for request gas limit
   * @return s_provingKeyHashes list of registered key hashes
   */
  function getRequestConfig()
    external
    view
    returns (
      uint16,
      uint32,
      bytes32[] memory
    );

  /**
   * @notice Request a set of random words.
   * @param keyHash - Corresponds to a particular oracle job which uses
   * that key for generating the VRF proof. Different keyHash's have different gas price
   * ceilings, so you can select a specific one to bound your maximum per request cost.
   * @param subId  - The ID of the VRF subscription. Must be funded
   * with the minimum subscription balance required for the selected keyHash.
   * @param minimumRequestConfirmations - How many blocks you'd like the
   * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS
   * for why you may want to request more. The acceptable range is
   * [minimumRequestBlockConfirmations, 200].
   * @param callbackGasLimit - How much gas you'd like to receive in your
   * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords
   * may be slightly less than this amount because of gas used calling the function
   * (argument decoding etc.), so you may need to request slightly more than you expect
   * to have inside fulfillRandomWords. The acceptable range is
   * [0, maxGasLimit]
   * @param numWords - The number of uint256 random values you'd like to receive
   * in your fulfillRandomWords callback. Note these numbers are expanded in a
   * secure way by the VRFCoordinator from a single random value supplied by the oracle.
   * @return requestId - A unique identifier of the request. Can be used to match
   * a request to a response in fulfillRandomWords.
   */
  function requestRandomWords(
    bytes32 keyHash,
    uint64 subId,
    uint16 minimumRequestConfirmations,
    uint32 callbackGasLimit,
    uint32 numWords
  ) external returns (uint256 requestId);

  /**
   * @notice Create a VRF subscription.
   * @return subId - A unique subscription id.
   * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.
   * @dev Note to fund the subscription, use transferAndCall. For example
   * @dev  LINKTOKEN.transferAndCall(
   * @dev    address(COORDINATOR),
   * @dev    amount,
   * @dev    abi.encode(subId));
   */
  function createSubscription() external returns (uint64 subId);

  /**
   * @notice Get a VRF subscription.
   * @param subId - ID of the subscription
   * @return balance - LINK balance of the subscription in juels.
   * @return reqCount - number of requests for this subscription, determines fee tier.
   * @return owner - owner of the subscription.
   * @return consumers - list of consumer address which are able to use this subscription.
   */
  function getSubscription(uint64 subId)
    external
    view
    returns (
      uint96 balance,
      uint64 reqCount,
      address owner,
      address[] memory consumers
    );

  /**
   * @notice Request subscription owner transfer.
   * @param subId - ID of the subscription
   * @param newOwner - proposed new owner of the subscription
   */
  function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external;

  /**
   * @notice Request subscription owner transfer.
   * @param subId - ID of the subscription
   * @dev will revert if original owner of subId has
   * not requested that msg.sender become the new owner.
   */
  function acceptSubscriptionOwnerTransfer(uint64 subId) external;

  /**
   * @notice Add a consumer to a VRF subscription.
   * @param subId - ID of the subscription
   * @param consumer - New consumer which can use the subscription
   */
  function addConsumer(uint64 subId, address consumer) external;

  /**
   * @notice Remove a consumer from a VRF subscription.
   * @param subId - ID of the subscription
   * @param consumer - Consumer to remove from the subscription
   */
  function removeConsumer(uint64 subId, address consumer) external;

  /**
   * @notice Cancel a subscription
   * @param subId - ID of the subscription
   * @param to - Where to send the remaining LINK to
   */
  function cancelSubscription(uint64 subId, address to) external;

  /*
   * @notice Check to see if there exists a request commitment consumers
   * for all consumers and keyhashes for a given sub.
   * @param subId - ID of the subscription
   * @return true if there exists at least one unfulfilled request for the subscription, false
   * otherwise.
   */
  function pendingRequestExists(uint64 subId) external view returns (bool);
}

File 6 of 36 : VRFConsumerBaseV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/** ****************************************************************************
 * @notice Interface for contracts using VRF randomness
 * *****************************************************************************
 * @dev PURPOSE
 *
 * @dev Reggie the Random Oracle (not his real job) wants to provide randomness
 * @dev to Vera the verifier in such a way that Vera can be sure he's not
 * @dev making his output up to suit himself. Reggie provides Vera a public key
 * @dev to which he knows the secret key. Each time Vera provides a seed to
 * @dev Reggie, he gives back a value which is computed completely
 * @dev deterministically from the seed and the secret key.
 *
 * @dev Reggie provides a proof by which Vera can verify that the output was
 * @dev correctly computed once Reggie tells it to her, but without that proof,
 * @dev the output is indistinguishable to her from a uniform random sample
 * @dev from the output space.
 *
 * @dev The purpose of this contract is to make it easy for unrelated contracts
 * @dev to talk to Vera the verifier about the work Reggie is doing, to provide
 * @dev simple access to a verifiable source of randomness. It ensures 2 things:
 * @dev 1. The fulfillment came from the VRFCoordinator
 * @dev 2. The consumer contract implements fulfillRandomWords.
 * *****************************************************************************
 * @dev USAGE
 *
 * @dev Calling contracts must inherit from VRFConsumerBase, and can
 * @dev initialize VRFConsumerBase's attributes in their constructor as
 * @dev shown:
 *
 * @dev   contract VRFConsumer {
 * @dev     constructor(<other arguments>, address _vrfCoordinator, address _link)
 * @dev       VRFConsumerBase(_vrfCoordinator) public {
 * @dev         <initialization with other arguments goes here>
 * @dev       }
 * @dev   }
 *
 * @dev The oracle will have given you an ID for the VRF keypair they have
 * @dev committed to (let's call it keyHash). Create subscription, fund it
 * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface
 * @dev subscription management functions).
 * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,
 * @dev callbackGasLimit, numWords),
 * @dev see (VRFCoordinatorInterface for a description of the arguments).
 *
 * @dev Once the VRFCoordinator has received and validated the oracle's response
 * @dev to your request, it will call your contract's fulfillRandomWords method.
 *
 * @dev The randomness argument to fulfillRandomWords is a set of random words
 * @dev generated from your requestId and the blockHash of the request.
 *
 * @dev If your contract could have concurrent requests open, you can use the
 * @dev requestId returned from requestRandomWords to track which response is associated
 * @dev with which randomness request.
 * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind,
 * @dev if your contract could have multiple requests in flight simultaneously.
 *
 * @dev Colliding `requestId`s are cryptographically impossible as long as seeds
 * @dev differ.
 *
 * *****************************************************************************
 * @dev SECURITY CONSIDERATIONS
 *
 * @dev A method with the ability to call your fulfillRandomness method directly
 * @dev could spoof a VRF response with any random value, so it's critical that
 * @dev it cannot be directly called by anything other than this base contract
 * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
 *
 * @dev For your users to trust that your contract's random behavior is free
 * @dev from malicious interference, it's best if you can write it so that all
 * @dev behaviors implied by a VRF response are executed *during* your
 * @dev fulfillRandomness method. If your contract must store the response (or
 * @dev anything derived from it) and use it later, you must ensure that any
 * @dev user-significant behavior which depends on that stored value cannot be
 * @dev manipulated by a subsequent VRF request.
 *
 * @dev Similarly, both miners and the VRF oracle itself have some influence
 * @dev over the order in which VRF responses appear on the blockchain, so if
 * @dev your contract could have multiple VRF requests in flight simultaneously,
 * @dev you must ensure that the order in which the VRF responses arrive cannot
 * @dev be used to manipulate your contract's user-significant behavior.
 *
 * @dev Since the block hash of the block which contains the requestRandomness
 * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
 * @dev miner could, in principle, fork the blockchain to evict the block
 * @dev containing the request, forcing the request to be included in a
 * @dev different block with a different hash, and therefore a different input
 * @dev to the VRF. However, such an attack would incur a substantial economic
 * @dev cost. This cost scales with the number of blocks the VRF oracle waits
 * @dev until it calls responds to a request. It is for this reason that
 * @dev that you can signal to an oracle you'd like them to wait longer before
 * @dev responding to the request (however this is not enforced in the contract
 * @dev and so remains effective only in the case of unmodified oracle software).
 */
abstract contract VRFConsumerBaseV2 {
  error OnlyCoordinatorCanFulfill(address have, address want);
  address private immutable vrfCoordinator;

  /**
   * @param _vrfCoordinator address of VRFCoordinator contract
   */
  constructor(address _vrfCoordinator) {
    vrfCoordinator = _vrfCoordinator;
  }

  /**
   * @notice fulfillRandomness handles the VRF response. Your contract must
   * @notice implement it. See "SECURITY CONSIDERATIONS" above for important
   * @notice principles to keep in mind when implementing your fulfillRandomness
   * @notice method.
   *
   * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this
   * @dev signature, and will call it once it has verified the proof
   * @dev associated with the randomness. (It is triggered via a call to
   * @dev rawFulfillRandomness, below.)
   *
   * @param requestId The Id initially returned by requestRandomness
   * @param randomWords the VRF output expanded to the requested number of words
   */
  function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual;

  // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
  // proof. rawFulfillRandomness then calls fulfillRandomness, after validating
  // the origin of the call
  function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external {
    if (msg.sender != vrfCoordinator) {
      revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator);
    }
    fulfillRandomWords(requestId, randomWords);
  }
}

File 7 of 36 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 8 of 36 : IERC1271.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 *
 * _Available since v4.1._
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with _data
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

File 9 of 36 : IERC1363Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1363Receiver.sol)

pragma solidity ^0.8.0;

interface IERC1363Receiver {
    /*
     * Note: the ERC-165 identifier for this interface is 0x88a7ca5c.
     * 0x88a7ca5c === bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))
     */

    /**
     * @notice Handle the receipt of ERC1363 tokens
     * @dev Any ERC1363 smart contract calls this function on the recipient
     * after a `transfer` or a `transferFrom`. This function MAY throw to revert and reject the
     * transfer. Return of other than the magic value MUST result in the
     * transaction being reverted.
     * Note: the token contract address is always the message sender.
     * @param operator address The address which called `transferAndCall` or `transferFromAndCall` function
     * @param from address The address which are token transferred from
     * @param value uint256 The amount of tokens transferred
     * @param data bytes Additional data with no specified format
     * @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))`
     *  unless throwing
     */
    function onTransferReceived(
        address operator,
        address from,
        uint256 value,
        bytes memory data
    ) external returns (bytes4);
}

File 10 of 36 : IERC1363Spender.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1363Spender.sol)

pragma solidity ^0.8.0;

interface IERC1363Spender {
    /*
     * Note: the ERC-165 identifier for this interface is 0x7b04a2d0.
     * 0x7b04a2d0 === bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))
     */

    /**
     * @notice Handle the approval of ERC1363 tokens
     * @dev Any ERC1363 smart contract calls this function on the recipient
     * after an `approve`. This function MAY throw to revert and reject the
     * approval. Return of other than the magic value MUST result in the
     * transaction being reverted.
     * Note: the token contract address is always the message sender.
     * @param owner address The address which called `approveAndCall` function
     * @param value uint256 The amount of tokens to be spent
     * @param data bytes Additional data with no specified format
     * @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))`
     *  unless throwing
     */
    function onApprovalReceived(
        address owner,
        uint256 value,
        bytes memory data
    ) external returns (bytes4);
}

File 11 of 36 : IERC2981.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;

import "../utils/introspection/IERC165.sol";

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

File 12 of 36 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 13 of 36 : ERC2981.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)

pragma solidity ^0.8.0;

import "../../interfaces/IERC2981.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
 *
 * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
 * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
 *
 * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
 * fee is specified in basis points by default.
 *
 * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
 * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 *
 * _Available since v4.5._
 */
abstract contract ERC2981 is IERC2981, ERC165 {
    struct RoyaltyInfo {
        address receiver;
        uint96 royaltyFraction;
    }

    RoyaltyInfo private _defaultRoyaltyInfo;
    mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @inheritdoc IERC2981
     */
    function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {
        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];

        if (royalty.receiver == address(0)) {
            royalty = _defaultRoyaltyInfo;
        }

        uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();

        return (royalty.receiver, royaltyAmount);
    }

    /**
     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
     * override.
     */
    function _feeDenominator() internal pure virtual returns (uint96) {
        return 10000;
    }

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: invalid receiver");

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Removes default royalty information.
     */
    function _deleteDefaultRoyalty() internal virtual {
        delete _defaultRoyaltyInfo;
    }

    /**
     * @dev Sets the royalty information for a specific token id, overriding the global default.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setTokenRoyalty(
        uint256 tokenId,
        address receiver,
        uint96 feeNumerator
    ) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: Invalid parameters");

        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Resets royalty information for the token id back to the global default.
     */
    function _resetTokenRoyalty(uint256 tokenId) internal virtual {
        delete _tokenRoyaltyInfo[tokenId];
    }
}

File 14 of 36 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
        }
        _balances[to] += amount;

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

File 15 of 36 : draft-ERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/draft-ERC20Permit.sol)

pragma solidity ^0.8.0;

import "./draft-IERC20Permit.sol";
import "../ERC20.sol";
import "../../../utils/cryptography/draft-EIP712.sol";
import "../../../utils/cryptography/ECDSA.sol";
import "../../../utils/Counters.sol";

/**
 * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * _Available since v3.4._
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
    using Counters for Counters.Counter;

    mapping(address => Counters.Counter) private _nonces;

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private constant _PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    /**
     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
     * However, to ensure consistency with the upgradeable transpiler, we will continue
     * to reserve a slot.
     * @custom:oz-renamed-from _PERMIT_TYPEHASH
     */
    // solhint-disable-next-line var-name-mixedcase
    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;

    /**
     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
     *
     * It's a good idea to use the same `name` that is defined as the ERC20 token name.
     */
    constructor(string memory name) EIP712(name, "1") {}

    /**
     * @dev See {IERC20Permit-permit}.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= deadline, "ERC20Permit: expired deadline");

        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        require(signer == owner, "ERC20Permit: invalid signature");

        _approve(owner, spender, value);
    }

    /**
     * @dev See {IERC20Permit-nonces}.
     */
    function nonces(address owner) public view virtual override returns (uint256) {
        return _nonces[owner].current();
    }

    /**
     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view override returns (bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev "Consume a nonce": return the current value and increment.
     *
     * _Available since v4.1._
     */
    function _useNonce(address owner) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[owner];
        current = nonce.current();
        nonce.increment();
    }
}

File 16 of 36 : draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 17 of 36 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 18 of 36 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 19 of 36 : ERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: address zero is not a valid owner");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not token owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
        _safeTransfer(from, to, tokenId, data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

        _afterTokenTransfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

File 20 of 36 : ERC721Burnable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/extensions/ERC721Burnable.sol)

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "../../../utils/Context.sol";

/**
 * @title ERC721 Burnable Token
 * @dev ERC721 Token that can be burned (destroyed).
 */
abstract contract ERC721Burnable is Context, ERC721 {
    /**
     * @dev Burns `tokenId`. See {ERC721-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) public virtual {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
        _burn(tokenId);
    }
}

File 21 of 36 : ERC721Royalty.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/ERC721Royalty.sol)

pragma solidity ^0.8.0;

import "../ERC721.sol";
import "../../common/ERC2981.sol";
import "../../../utils/introspection/ERC165.sol";

/**
 * @dev Extension of ERC721 with the ERC2981 NFT Royalty Standard, a standardized way to retrieve royalty payment
 * information.
 *
 * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
 * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
 *
 * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
 * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 *
 * _Available since v4.5._
 */
abstract contract ERC721Royalty is ERC2981, ERC721 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {ERC721-_burn}. This override additionally clears the royalty information for the token.
     */
    function _burn(uint256 tokenId) internal virtual override {
        super._burn(tokenId);
        _resetTokenRoyalty(tokenId);
    }
}

File 22 of 36 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 23 of 36 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

File 24 of 36 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 25 of 36 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 26 of 36 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 27 of 36 : Counters.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

File 28 of 36 : draft-EIP712.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)

pragma solidity ^0.8.0;

import "./ECDSA.sol";

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
    /* solhint-disable var-name-mixedcase */
    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
    uint256 private immutable _CACHED_CHAIN_ID;
    address private immutable _CACHED_THIS;

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;

    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        bytes32 typeHash = keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
        _CACHED_CHAIN_ID = block.chainid;
        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
        _CACHED_THIS = address(this);
        _TYPE_HASH = typeHash;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
            return _CACHED_DOMAIN_SEPARATOR;
        } else {
            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
        }
    }

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }
}

File 29 of 36 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

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

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

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

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

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

    /**
     * @dev Returns true if the `leaves` can be proved to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and the sibling nodes in `proof`,
     * consuming from one or the other at each step according to the instructions given by
     * `proofFlags`.
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

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

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

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

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

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

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

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

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

File 31 of 36 : SignatureChecker.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.1) (utils/cryptography/SignatureChecker.sol)

pragma solidity ^0.8.0;

import "./ECDSA.sol";
import "../Address.sol";
import "../../interfaces/IERC1271.sol";

/**
 * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
 * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
 * Argent and Gnosis Safe.
 *
 * _Available since v4.1._
 */
library SignatureChecker {
    /**
     * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
     * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
     *
     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
     * change through time. It could return true at block N and false at block N+1 (or the opposite).
     */
    function isValidSignatureNow(
        address signer,
        bytes32 hash,
        bytes memory signature
    ) internal view returns (bool) {
        (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
        if (error == ECDSA.RecoverError.NoError && recovered == signer) {
            return true;
        }

        (bool success, bytes memory result) = signer.staticcall(
            abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
        );
        return (success &&
            result.length == 32 &&
            abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
    }
}

File 32 of 36 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 33 of 36 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 34 of 36 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

File 35 of 36 : ERC2771ContextFromStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/// @notice OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol)
import "../libs/@openzeppelin/contracts/utils/Context.sol";

/**
 * @dev Context variant with ERC2771 support using a non-immutable storage variable.
 */
abstract contract ERC2771ContextFromStorage is Context {
    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
    address internal _trustedForwarder;

    event NewTrustedForwarder(address indexed trustedForwarder);

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor(address trustedForwarder) {
        _trustedForwarder = trustedForwarder;
    }

    function isTrustedForwarder(address forwarder) public view virtual returns (bool) {
        return forwarder == _trustedForwarder;
    }

    function _msgSender() internal view virtual override returns (address sender) {
        if (isTrustedForwarder(msg.sender)) {
            // The assembly code is more direct than the Solidity version using `abi.decode`.
            /// @solidity memory-safe-assembly
            assembly {
                sender := shr(96, calldataload(sub(calldatasize(), 20)))
            }
        } else {
            return super._msgSender();
        }
    }

    function _msgData() internal view virtual override returns (bytes calldata) {
        if (isTrustedForwarder(msg.sender)) {
            return msg.data[:msg.data.length - 20];
        } else {
            return super._msgData();
        }
    }
}

File 36 of 36 : NeowizERC721.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "./libs/@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./libs/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
import "./libs/@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "./libs/@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol";
import "./libs/@openzeppelin/contracts/access/Ownable.sol";
import "./libs/@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "./libs/@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "./libs/@openzeppelin/contracts/interfaces/IERC1363Receiver.sol";
import "./libs/@openzeppelin/contracts/interfaces/IERC1363Spender.sol";
import "./metatx/ERC2771ContextFromStorage.sol";
import "./erc721-permits/ERC721WithPermit.sol";
import "./interfaces/INeowizERC721.sol";

/**
 * @title NeowiERC721
 * @notice The minting process goes as follows.
 *   0. setBaseURI
 *   1. teamMint: The contract owner can call anytime even during the minting round. It is usually called before the first minting round starts.
 *   2. privateMint, publicMint: The total mintable amount in the last round is (round.maxMint + leftover amounts in the previous rounds).
 *   3. mintResidue: The owner should mint all to reveal the collection.
 *   4. requestRandomSeed: To reveal, the contract owner should call this function to get the random seed.
 */
abstract contract NeowizERC721 is
    INeowizERC721,
    IERC1363Receiver,
    IERC1363Spender,
    ERC721Burnable,
    ERC721Royalty,
    ERC721WithPermit,
    ERC2771ContextFromStorage,
    ReentrancyGuard,
    Ownable
{
    error NotExistingRound();
    error ZeroMaxTotalSupply();
    error WrongSaleRound();
    error RoundNotStarted();
    error InvalidTimestamp();
    error RoundEnded();
    error NotPublic();
    error NotPrivate();
    error NotSoldout();
    error NotAllRoundsFinished();
    error IncorrectProof();
    error NotEnoughFund();
    error NotEnoughERC20Fund();
    error PriceNotSet();
    error MaxMintExceeded(uint256 round);
    error MaxMintPerAccountExceeded(uint256 round, address account);
    error MaxTotalSupplyExceeded();
    error MaxTotalTeamMintExceeded();
    error AlreadyRevealed();
    error InvalidCollectorRatio();
    error AddressZero();

    address public immutable team;

    // base uri for nfts
    string private baseURI;

    // Valid currentRound starts from 1, and default is 0.
    uint256 private _currentRound;

    // The next token ID to be team-minted.
    uint256 private _currentTeamIndex;

    // The next token ID to be minted.
    uint256 private _currentIndex;

    // The number of tokens burned.
    uint256 private _burnCounter;

    // Operator
    address private _operator;

    uint256 public numRounds;
    mapping(uint256 => Round) public rounds;

    address public payment;
    uint256 public randomSeed;
    bool public revealed;
    string public unrevealedURI;
    uint256 public immutable TEAM_SUPPLY;
    uint256 public immutable MAX_TOTAL_SUPPLY;

    struct SalesInfo {
        address collector1;
        address collector2;
        uint16 collector1Ratio;
    }
    SalesInfo public salesInfo;

    uint16 public constant ratioDenominator = 10000;

    enum SaleState {
        PRIVATE,
        PUBLIC
    }

    /**
     * @dev In a round, users can mint until `round.totalMinted` == `round.maxMint`.
     * If it is the last round, users can mint more than maxMint until totalSupply() == MAX_TOTAL_SUPPLY.
     * `numberMinted` is necessary to allow users to mint multiple times in a round,
     * as long as they have minted less than `MAX_MINT_PER_ACCOUNT` in the round.;
     * @param state The minting round proceeds like CLOSED -> OG -> WL -> PUBLIC_0 -> PUBLIC_1.
     * However, any rounds may be omitted, i.e. a minting with only WL round is possible.
     */
    struct Round {
        mapping(address => uint256) numberMinted;
        uint256 maxMintPerAccount;
        uint256 maxMint;
        uint256 totalMinted;
        uint256 price;
        SaleState state;
        bytes32 merkleRoot;
        uint64 startTs;
        uint64 endTs;
    }

    /// @param _name name in ERC721
    /// @param _symbol symbol in ERC721
    /// @param _maxTotalSupply The max number of NFTs to be minted
    /// @param _teamSupply The reserved quantity for team
    /// @param _team address of team
    /// @param _payment address of ERC20 token to be paid when minting NFT. address(0) is ETH.
    /// @param _unrevealedURI ipfs uri when NFT has not yet revealed
    /// @param _trustedForwarder address of ERC2771 forwarder
    constructor(
        string memory _name,
        string memory _symbol,
        uint256 _maxTotalSupply,
        uint256 _teamSupply,
        address _team,
        address _payment,
        string memory _unrevealedURI,
        address _trustedForwarder,
        SalesInfo memory _salesInfo
    ) ERC721(_name, _symbol) ERC2771ContextFromStorage(_trustedForwarder) {
        if (_salesInfo.collector1 == address(0) || _salesInfo.collector2 == address(0)) {
            revert AddressZero();
        }
        if (_maxTotalSupply == 0) {
            revert ZeroMaxTotalSupply();
        }
        if (_salesInfo.collector1Ratio > ratioDenominator) {
            revert InvalidCollectorRatio();
        }
        MAX_TOTAL_SUPPLY = _maxTotalSupply;
        TEAM_SUPPLY = _currentIndex = _teamSupply;
        team = _team;
        payment = _payment;
        unrevealedURI = _unrevealedURI;
        salesInfo = _salesInfo;
    }

    modifier onlyOperator() {
        require(
            operator() == _msgSender() || owner() == _msgSender(),
            "NeowizERC721: caller is not the operator or owner"
        );
        _;
    }

    modifier whenSoldout() {
        if (totalMinted() < MAX_TOTAL_SUPPLY) {
            revert NotSoldout();
        }
        _;
    }

    modifier inRound(uint256 _round) {
        Round storage round = rounds[_round];
        if (numRounds < _round) {
            revert WrongSaleRound();
        }
        if (block.timestamp < round.startTs) {
            revert RoundNotStarted();
        }
        if (round.endTs <= block.timestamp) {
            revert RoundEnded();
        }
        _;
    }

    modifier isPublic(uint256 _round) {
        if (rounds[_round].state != SaleState.PUBLIC) {
            revert NotPublic();
        }
        _;
    }

    modifier isPrivate(uint256 _round) {
        SaleState state = rounds[_round].state;
        if (state != SaleState.PRIVATE) {
            revert NotPrivate();
        }
        _;
    }

    modifier checkRound(uint256 _roundId) {
        if (numRounds < _roundId) {
            revert NotExistingRound();
        }
        _;
    }

    /// @dev onlyOwner
    function setOperator(address newOperator) external onlyOwner {
        require(newOperator != address(0), "NeowizERC721: new operator is the zero address");
        _setOperator(newOperator);
    }

    /// @dev onlyOwner
    function setTrustedForwarder(address _forwarder) external onlyOwner {
        _trustedForwarder = _forwarder;
        emit NewTrustedForwarder(_forwarder);
    }

    function burn(uint256 tokenId) public override(INeowizERC721, ERC721Burnable) {
        super.burn(tokenId);
        _burnCounter++;
    }

    /// @dev onlyOperator
    function setPayment(address _payment) external onlyOperator {
        payment = _payment;
        emit PaymentUpdated(_payment);
    }

    /// @dev onlyOperator
    function setUnRevealedURI(string memory _unrevealedURI) external onlyOperator {
        unrevealedURI = _unrevealedURI;
        emit UnrevealedURIUpdated(_unrevealedURI);
    }

    /// @notice Add a minting round
    /// @dev onlyOperator
    /// @param _state private or public
    /// @param _maxMintPerAccount The max amount of tokens one account can mint in this round
    /// @param _maxMint The max amount of tokens reserved in this round
    /// @param _price The unit price per token
    /// @param _merkleRoot This is useful only in a private round
    /// @param _startTs The timestamp when this round starts
    /// @param _endTs The timestamp when this round ends
    function addRound(
        SaleState _state,
        uint256 _maxMintPerAccount,
        uint256 _maxMint,
        uint256 _price,
        bytes32 _merkleRoot,
        uint256 _startTs,
        uint256 _endTs
    ) external onlyOperator {
        if (_endTs < _startTs) {
            revert InvalidTimestamp();
        }
        if (_startTs < rounds[numRounds].endTs) {
            revert InvalidTimestamp();
        }

        Round storage r = rounds[++numRounds];
        r.state = _state;
        r.maxMintPerAccount = _maxMintPerAccount;
        r.maxMint = _maxMint;
        r.price = _price;
        r.merkleRoot = _merkleRoot;
        r.startTs = uint64(_startTs);
        r.endTs = uint64(_endTs);

        emit RoundAdded(
            numRounds,
            uint256(_state),
            _maxMintPerAccount,
            _maxMint,
            _price,
            _merkleRoot,
            _startTs,
            _endTs
        );
    }

    /// @dev onlyOperator
    function updateState(uint256 _roundId, SaleState _state) external checkRound(_roundId) onlyOperator {
        Round storage r = rounds[_roundId];
        r.state = _state;

        emit StateUpdated(_roundId, uint256(_state));
    }

    /// @dev onlyOperator
    function updateMaxMint(uint256 _roundId, uint256 _maxMint) external checkRound(_roundId) onlyOperator {
        Round storage r = rounds[_roundId];
        r.maxMint = _maxMint;
        emit MaxMintUpdated(_roundId, _maxMint);
    }

    /// @dev onlyOperator
    function updateMaxMintPerAccount(
        uint256 _roundId,
        uint256 _maxMintPerAccount
    ) external checkRound(_roundId) onlyOperator {
        Round storage r = rounds[_roundId];
        r.maxMintPerAccount = _maxMintPerAccount;
        emit MaxMintPerAccountUpdated(_roundId, _maxMintPerAccount);
    }

    /// @dev onlyOperator
    function updatePrice(uint256 _roundId, uint256 _price) external checkRound(_roundId) onlyOperator {
        Round storage r = rounds[_roundId];
        r.price = _price;
        emit PriceUpdated(_roundId, _price);
    }

    /// @dev onlyOperator
    function updateMerkleRoot(uint256 _roundId, bytes32 _merkleRoot) external checkRound(_roundId) onlyOperator {
        Round storage r = rounds[_roundId];
        r.merkleRoot = _merkleRoot;
        emit MerkleRootUpdated(_roundId, _merkleRoot);
    }

    /// @dev onlyOperator
    /// @param _startTs _startTs must >= endTs of the previous round
    /// @param _endTs _endTs must <= startTs of the next round
    function updateRoundTimestamp(
        uint256 _roundId,
        uint256 _startTs,
        uint256 _endTs
    ) external checkRound(_roundId) onlyOperator {
        if (_endTs < _startTs) {
            revert InvalidTimestamp();
        }
        Round storage r = rounds[_roundId];

        if (_roundId < numRounds && rounds[_roundId + 1].startTs < _endTs) {
            revert InvalidTimestamp();
        }

        if (1 < _roundId && _startTs < rounds[_roundId - 1].endTs) {
            revert InvalidTimestamp();
        }

        r.startTs = uint64(_startTs);
        r.endTs = uint64(_endTs);

        emit RoundTimestampUpdated(_roundId, _startTs, _endTs);
    }

    /// @dev onlyOperator
    function setBaseURI(string memory _uri) external onlyOperator {
        require(bytes(_uri).length > 0, "wrong base uri");
        baseURI = _uri;
        emit BaseURIUpdated(_uri);
    }

    /// @notice Sets the contract-wide ERC-2981 royalty info.
    /// @dev onlyOwner
    /// @param receiver Royalty receiver address
    /// @param feeBasisPoints The fee rate is equal to `feeBasisPoint / ERC2981._feeDenominator()`
    function setRoyaltyInfo(address receiver, uint96 feeBasisPoints) external onlyOwner {
        _setDefaultRoyalty(receiver, feeBasisPoints);
        emit RoyaltyInfoUpdated(receiver, feeBasisPoints);
    }

    /// @notice Mint unminted nfts to `team` before the reveal. This excludes the team amount.
    /// @dev onlyOperator
    /// @param _quantity Given type(uint256).max, mint all remainders except for the team amount.
    function mintResidue(uint256 _quantity) external onlyOperator {
        // Check
        if (_quantity == type(uint256).max) {
            _quantity = _notTeamResidue();
        }
        if (block.timestamp < rounds[numRounds].endTs) {
            revert NotAllRoundsFinished();
        }
        if (_notTeamResidue() < _quantity) {
            revert MaxTotalSupplyExceeded();
        }

        // Effect
        _currentIndex += _quantity;

        // Interaction
        _mintNotTeamQuantity(team, _quantity);
    }

    /// @notice Mint to `team`
    /// @dev onlyOperator
    /// @param _quantity The number of tokens to mint.
    function teamMint(uint256 _quantity) external onlyOperator {
        if (_quantity == type(uint256).max) {
            _quantity = TEAM_SUPPLY - totalTeamMinted();
        }
        if (TEAM_SUPPLY < totalTeamMinted() + _quantity) {
            revert MaxTotalTeamMintExceeded();
        }

        _currentTeamIndex += _quantity;

        _mintTeamQuantity(team, _quantity);
    }

    /// @notice Mint a public drop
    /// @param _quantity The number of tokens to mint.
    /// @param _round The round id
    /// @param _payment The payment token address
    /// @param _price The price of one nft
    function publicMint(uint256 _quantity, uint256 _round, address _payment, uint256 _price) external payable {
        _publicMint(_msgSender(), false, _quantity, _round, _payment, _price);
    }

    function _publicMint(
        address _from,
        bool _isPaid,
        uint256 _quantity,
        uint256 _round,
        address _payment,
        uint256 _price
    ) internal inRound(_round) isPublic(_round) {
        Round storage round = rounds[_round];
        require(_payment == address(payment), "payment is different");
        require(_price == round.price, "round price is different");

        if (!_isPaid) {
            _payMintFee(_from, round.price * _quantity);
        }
        _mintInRound(_round, _from, _quantity);
    }

    /// @notice Mint a private drop
    /// @dev Private round only allows whitelisted users.
    /// @param _merkleProof The proof for the leaf of the whitelist.
    /// @param _quantity The number of tokens to mint.
    /// @param _round The round id
    /// @param _payment The payment token address
    /// @param _price The price of one nft
    function privateMint(
        bytes32[] calldata _merkleProof,
        uint256 _quantity,
        uint256 _round,
        address _payment,
        uint256 _price
    ) external payable {
        _privateMint(_msgSender(), false, _merkleProof, _quantity, _round, _payment, _price);
    }

    function _privateMint(
        address _from,
        bool _isPaid,
        bytes32[] memory _merkleProof,
        uint256 _quantity,
        uint256 _round,
        address _payment,
        uint256 _price
    ) internal inRound(_round) isPrivate(_round) {
        Round storage round = rounds[_round];
        require(_payment == address(payment), "payment is different");
        require(_price == round.price, "round price is different");

        checkValidity(_merkleProof, rounds[_round].merkleRoot, _from);
        if (!_isPaid) {
            _payMintFee(_from, round.price * _quantity);
        }
        _mintInRound(_round, _from, _quantity);
    }

    /// @notice Mint a public drop with ERC20 permit signature
    /// @param _quantity The number of tokens to mint.
    /// @param _round The round id
    /// @param _payment The payment token address
    /// @param _price The price of one nft
    /// @param v ERC20Permit signature v from the`owner`
    /// @param r ERC20Permit signature r from the`owner`
    /// @param s ERC20Permit signature s from the`owner`
    function publicMintWithPermit(
        uint256 _quantity,
        uint256 _round,
        address _payment,
        uint256 _price,
        uint256 _deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        _permitPayment(_price * _quantity, _deadline, v, r, s);
        _publicMint(_msgSender(), false, _quantity, _round, _payment, _price);
    }

    /// @notice Mint a private drop with ERC20 permit signature
    /// @dev Private round only allows whitelisted users.
    /// @param _merkleProof The proof for the leaf of the whitelist.
    /// @param _quantity The number of tokens to mint.
    /// @param _round The round id
    /// @param _payment The payment token address
    /// @param _price The price of one nft
    /// @param v ERC20Permit signature v from the`owner`
    /// @param r ERC20Permit signature r from the`owner`
    /// @param s ERC20Permit signature s from the`owner`
    function privateMintWithPermit(
        bytes32[] calldata _merkleProof,
        uint256 _quantity,
        uint256 _round,
        address _payment,
        uint256 _price,
        uint256 _deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external payable {
        _permitPayment(_price * _quantity, _deadline, v, r, s);
        _privateMint(_msgSender(), false, _merkleProof, _quantity, _round, _payment, _price);
    }

    /// @notice Check the given merkle proof is valid
    /// @dev   All leaf nodes are hashed using keccak256
    /// @param _merkleProof The proof for the leaf of the whitelist.
    /// @param _root The merkle root
    /// @param _to The address to be checked
    function checkValidity(bytes32[] memory _merkleProof, bytes32 _root, address _to) public pure {
        bytes32 leaf = keccak256(abi.encodePacked(_to));
        if (!MerkleProof.verify(_merkleProof, _root, leaf)) {
            revert IncorrectProof();
        }
    }

    /// @notice Withdraw the minting revenue
    /// @dev onlyOperator
    /// @param _amount the amount to send
    function withdraw(uint256 _amount) external onlyOperator nonReentrant {
        uint256 amount = _amount;
        if (amount == type(uint256).max) {
            amount = payment == address(0) ? address(this).balance : IERC20(payment).balanceOf(address(this));
        }
        uint256 amount1 = (amount * salesInfo.collector1Ratio) / ratioDenominator;
        uint256 amount2 = amount - amount1;
        if (address(payment) == address(0)) {
            (bool success, ) = payable(salesInfo.collector1).call{value: amount1}("");
            require(success);
            (success, ) = payable(salesInfo.collector2).call{value: amount2}("");
            require(success);
        } else {
            IERC20(payment).transfer(salesInfo.collector1, amount1);
            IERC20(payment).transfer(salesInfo.collector2, amount2);
        }
    }

    // ************* internal functions *************
    function _setOperator(address newOperator) internal virtual {
        _operator = newOperator;
        emit NewOperator(newOperator);
    }

    /**
     * @notice It is allowed to set the random seed after all tokens are minted.
     */
    function _setRandomSeed(uint256 _randomSeed) internal {
        if (revealed) {
            revert AlreadyRevealed();
        }
        randomSeed = _randomSeed % (MAX_TOTAL_SUPPLY - TEAM_SUPPLY);
        revealed = true;

        emit Revealed();
    }

    function _permitPayment(uint256 value, uint256 _deadline, uint8 v, bytes32 r, bytes32 s) internal {
        IERC20Permit(payment).permit(_msgSender(), address(this), value, _deadline, v, r, s);
    }

    function _payMintFee(address _payer, uint256 _amount) internal {
        if (payment != address(0)) {
            if (IERC20(payment).balanceOf(_payer) < _amount) {
                revert NotEnoughERC20Fund();
            }
            IERC20(payment).transferFrom(_payer, address(this), _amount);
        } else {
            if (msg.value < _amount) {
                revert NotEnoughFund();
            }
        }
    }

    /// @dev tokenId is guaranteed to be less than `MAX_TOTAL_SUPPLY`.
    function _mintInRound(uint256 _round, address _to, uint256 _quantity) internal {
        // check
        Round storage round = rounds[_round];

        if (round.maxMintPerAccount < round.numberMinted[_to] + _quantity) {
            revert MaxMintPerAccountExceeded(_round, _to);
        }

        // Skip round.maxMint check if it is the last round
        if (_round != numRounds && round.maxMint < (round.totalMinted + _quantity)) {
            revert MaxMintExceeded(_round);
        }

        if (_notTeamResidue() < _quantity) {
            revert MaxTotalSupplyExceeded();
        }

        // effect
        round.numberMinted[_to] += _quantity;
        round.totalMinted += _quantity;
        _currentIndex += _quantity;

        // interaction
        _mintNotTeamQuantity(_to, _quantity);
    }

    function _transfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721WithPermit) {
        super._transfer(from, to, tokenId);
    }

    function _burn(uint256 tokenId) internal override(ERC721, ERC721Royalty) {
        super._burn(tokenId);
    }

    /// @dev Before this, increase _currentTeamIndex and check all validations
    function _mintTeamQuantity(address _to, uint256 _quantity) private {
        uint256 startId = _currentTeamIndex - _quantity;
        for (uint256 i = startId; i < startId + _quantity; i++) {
            _safeMint(_to, i);
        }
    }

    /// @dev Before this, increase _currentIndex and check all validations
    function _mintNotTeamQuantity(address _to, uint256 _quantity) private {
        uint256 startId = _currentIndex - _quantity;
        for (uint256 i = startId; i < startId + _quantity; i++) {
            _safeMint(_to, i);
        }
    }

    // ************* view functions *************
    /// @notice Query if a contract implements an interface
    /// @param interfaceId The interface identifier, as specified in ERC-165
    function supportsInterface(
        bytes4 interfaceId
    ) public view override(ERC721, ERC721Royalty, ERC721WithPermit) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    /**
     * @notice Returns the address of operator
     */
    function operator() public view virtual returns (address) {
        return _operator;
    }

    /// @notice Returns whether the NFT is revealed
    function isRevealed() public view override returns (bool) {
        return revealed;
    }

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() public view returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented more than `_currentIndex` times.
        unchecked {
            return totalMinted() - _burnCounter;
        }
    }

    /**
     * @notice Returns the total amount of tokens minted in the contract.
     */
    function totalMinted() public view returns (uint256) {
        unchecked {
            return _currentIndex - TEAM_SUPPLY + _currentTeamIndex;
        }
    }

    /**
     * @notice Returns the total amount of tokens minted by the team.
     */
    function totalTeamMinted() public view returns (uint256) {
        return _currentTeamIndex;
    }

    /**
     * @notice Returns the current round number
     */
    function currentRound() public view returns (uint256) {
        Round storage r;
        for (uint256 i = 1; i <= numRounds; i++) {
            r = rounds[i];
            if (r.startTs <= block.timestamp && block.timestamp < r.endTs) {
                return i;
            }
        }

        return 0;
    }

    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT.
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

        if (!revealed) {
            return unrevealedURI;
        }

        uint256 shiftedId;
        if (tokenId < TEAM_SUPPLY) {
            shiftedId = tokenId;
        } else {
            shiftedId = ((tokenId - TEAM_SUPPLY + randomSeed) % (MAX_TOTAL_SUPPLY - TEAM_SUPPLY)) + TEAM_SUPPLY;
        }

        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, Strings.toString(shiftedId))) : "";
    }

    /// @notice Returns how many tokens the account minted in the round
    function numberMintedInRound(address _account, uint256 _round) external view returns (uint256) {
        return rounds[_round].numberMinted[_account];
    }

    function _notTeamResidue() internal view returns (uint256) {
        unchecked {
            return MAX_TOTAL_SUPPLY - _currentIndex;
        }
    }

    function _baseURI() internal view override returns (string memory) {
        return baseURI;
    }

    event TransferReceived(address token, address operator, address from, uint256 amount, bytes data);
    event ApprovalReceived(address token, address owner, uint256 amount, bytes data);

    modifier onlyPayment() {
        require(msg.sender == address(payment), "only ERC1363 payment");
        _;
    }

    function onTransferReceived(
        address _sender,
        address _from,
        uint256 _amount,
        bytes calldata _data
    ) external override onlyPayment returns (bytes4) {
        emit TransferReceived(msg.sender, _sender, _from, _amount, _data);

        bytes4 selector = bytes4(_data[:4]);
        bytes calldata data = _data[4:];
        if (selector == this.publicMint.selector) {
            (uint256 _quantity, uint256 _round, address _payment, uint256 _price) = abi.decode(
                data,
                (uint256, uint256, address, uint256)
            );
            require(_quantity * _price == _amount, "onTransferReceived: invalid amount");

            _publicMint(_from, true, _quantity, _round, _payment, _price);
        } else if (selector == this.privateMint.selector) {
            (bytes32[] memory _merkleProof, uint256 _quantity, uint256 _round, address _payment, uint256 _price) = abi
                .decode(data, (bytes32[], uint256, uint256, address, uint256));
            require(_quantity * _price == _amount, "onTransferReceived: invalid amount");

            _privateMint(_from, true, _merkleProof, _quantity, _round, _payment, _price);
        } else {
            revert("onTransferReceived: function selector not supported");
        }
        return this.onTransferReceived.selector;
    }

    function onApprovalReceived(
        address _owner,
        uint256 _amount,
        bytes calldata _data
    ) external override onlyPayment returns (bytes4) {
        emit ApprovalReceived(msg.sender, _owner, _amount, _data);

        bytes4 selector = bytes4(_data[:4]);
        bytes memory data = _data[4:];
        if (selector == this.publicMint.selector) {
            (uint256 _quantity, uint256 _round, address _payment, uint256 _price) = abi.decode(
                data,
                (uint256, uint256, address, uint256)
            );
            _publicMint(_owner, false, _quantity, _round, _payment, _price);
        } else if (selector == this.privateMint.selector) {
            (bytes32[] memory _merkleProof, uint256 _quantity, uint256 _round, address _payment, uint256 _price) = abi
                .decode(data, (bytes32[], uint256, uint256, address, uint256));
            _privateMint(_owner, false, _merkleProof, _quantity, _round, _payment, _price);
        } else {
            revert("onApprovalReceived: function selector not supported");
        }
        return this.onApprovalReceived.selector;
    }

    function _msgSender() internal view virtual override(Context, ERC2771ContextFromStorage) returns (address sender) {
        return super._msgSender();
    }

    function _msgData() internal view virtual override(Context, ERC2771ContextFromStorage) returns (bytes calldata) {
        return super._msgData();
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_maxTotalSupply","type":"uint256"},{"internalType":"uint256","name":"_teamSupply","type":"uint256"},{"internalType":"address","name":"_team","type":"address"},{"internalType":"address","name":"_payment","type":"address"},{"internalType":"string","name":"_unrevealedURI","type":"string"},{"internalType":"address","name":"_trustedForwarder","type":"address"},{"internalType":"uint64","name":"_subscriptionId","type":"uint64"},{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"components":[{"internalType":"address","name":"collector1","type":"address"},{"internalType":"address","name":"collector2","type":"address"},{"internalType":"uint16","name":"collector1Ratio","type":"uint16"}],"internalType":"struct NeowizERC721.SalesInfo","name":"_salesInfo","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressZero","type":"error"},{"inputs":[],"name":"AlreadyRevealed","type":"error"},{"inputs":[],"name":"IncorrectProof","type":"error"},{"inputs":[],"name":"InvalidCollectorRatio","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[{"internalType":"uint256","name":"round","type":"uint256"}],"name":"MaxMintExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"round","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"MaxMintPerAccountExceeded","type":"error"},{"inputs":[],"name":"MaxTotalSupplyExceeded","type":"error"},{"inputs":[],"name":"MaxTotalTeamMintExceeded","type":"error"},{"inputs":[],"name":"NotAllRoundsFinished","type":"error"},{"inputs":[],"name":"NotEnoughERC20Fund","type":"error"},{"inputs":[],"name":"NotEnoughFund","type":"error"},{"inputs":[],"name":"NotExistingRound","type":"error"},{"inputs":[],"name":"NotPrivate","type":"error"},{"inputs":[],"name":"NotPublic","type":"error"},{"inputs":[],"name":"NotSoldout","type":"error"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[],"name":"PriceNotSet","type":"error"},{"inputs":[],"name":"RoundEnded","type":"error"},{"inputs":[],"name":"RoundNotStarted","type":"error"},{"inputs":[],"name":"WrongSaleRound","type":"error"},{"inputs":[],"name":"ZeroMaxTotalSupply","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ApprovalReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"BaseURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxMint","type":"uint256"}],"name":"MaxMintPerAccountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxMint","type":"uint256"}],"name":"MaxMintUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"MerkleRootUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"NewOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trustedForwarder","type":"address"}],"name":"NewTrustedForwarder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"payment","type":"address"}],"name":"PaymentUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"PriceUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"Revealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"state","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxMintPerAccount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxMint","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"startTs","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTs","type":"uint256"}],"name":"RoundAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTs","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTs","type":"uint256"}],"name":"RoundTimestampUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeBasisPoints","type":"uint96"}],"name":"RoyaltyInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"state","type":"uint256"}],"name":"StateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"TransferReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"UnrevealedURIUpdated","type":"event"},{"inputs":[],"name":"COORDINATOR","outputs":[{"internalType":"contract VRFCoordinatorV2Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOTAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TEAM_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"_buildDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum NeowizERC721.SaleState","name":"_state","type":"uint8"},{"internalType":"uint256","name":"_maxMintPerAccount","type":"uint256"},{"internalType":"uint256","name":"_maxMint","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"_startTs","type":"uint256"},{"internalType":"uint256","name":"_endTs","type":"uint256"}],"name":"addRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"address","name":"_to","type":"address"}],"name":"checkValidity","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"currentRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRevealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"mintResidue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numRounds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_round","type":"uint256"}],"name":"numberMintedInRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onApprovalReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onTransferReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"operator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payment","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_round","type":"uint256"},{"internalType":"address","name":"_payment","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"privateMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_round","type":"uint256"},{"internalType":"address","name":"_payment","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"privateMintWithPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_round","type":"uint256"},{"internalType":"address","name":"_payment","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_round","type":"uint256"},{"internalType":"address","name":"_payment","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"publicMintWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"randomSeed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ratioDenominator","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_keyHash","type":"bytes32"},{"internalType":"uint16","name":"_requestConfirmations","type":"uint16"},{"internalType":"uint32","name":"_callbackGasLimit","type":"uint32"}],"name":"requestRandomSeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rounds","outputs":[{"internalType":"uint256","name":"maxMintPerAccount","type":"uint256"},{"internalType":"uint256","name":"maxMint","type":"uint256"},{"internalType":"uint256","name":"totalMinted","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"enum NeowizERC721.SaleState","name":"state","type":"uint8"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint64","name":"startTs","type":"uint64"},{"internalType":"uint64","name":"endTs","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"salesInfo","outputs":[{"internalType":"address","name":"collector1","type":"address"},{"internalType":"address","name":"collector2","type":"address"},{"internalType":"uint16","name":"collector1Ratio","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOperator","type":"address"}],"name":"setOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_payment","type":"address"}],"name":"setPayment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeBasisPoints","type":"uint96"}],"name":"setRoyaltyInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_forwarder","type":"address"}],"name":"setTrustedForwarder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_unrevealedURI","type":"string"}],"name":"setUnRevealedURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subscriptionId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"team","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"teamMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTeamMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unrevealedURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"uint256","name":"_maxMint","type":"uint256"}],"name":"updateMaxMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"uint256","name":"_maxMintPerAccount","type":"uint256"}],"name":"updateMaxMintPerAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"name":"updateMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"updatePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"uint256","name":"_startTs","type":"uint256"},{"internalType":"uint256","name":"_endTs","type":"uint256"}],"name":"updateRoundTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"enum NeowizERC721.SaleState","name":"_state","type":"uint8"}],"name":"updateState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101406040523480156200001257600080fd5b50604051620064ad380380620064ad833981016040819052620000359162000595565b6001600160a01b0382166080528a8a8a8a8a8a8a8a8881898960026200005c83826200074c565b5060036200006b82826200074c565b50504660c08190529050620000808162000236565b60a05250600980546001600160a01b0319166001600160a01b03929092169190911790556001600a55620000bd620000b7620002e4565b620002f5565b80516001600160a01b03161580620000e0575060208101516001600160a01b0316155b15620000ff57604051639fabe1c160e01b815260040160405180910390fd5b8660000362000121576040516308bdabe560e21b815260040160405180910390fd5b61271061ffff16816040015161ffff1611156200015157604051632a2a033560e21b815260040160405180910390fd5b610120879052600f8690556101008690526001600160a01b0385811660e052601480546001600160a01b03191691861691909117905560176200019584826200074c565b508051601880546001600160a01b039283166001600160a01b031990911617905560208201516019805460409094015161ffff16600160a01b026001600160b01b03199094169183169190911792909217909155601a80549b90911668010000000000000000026001600160e01b0319909b166001600160401b03909c169b909b179990991790995550620008189f50505050505050505050505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6200026362000347565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6000620002f0620003e1565b905090565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060600280546200035890620006bb565b80601f01602080910402602001604051908101604052809291908181526020018280546200038690620006bb565b8015620003d75780601f10620003ab57610100808354040283529160200191620003d7565b820191906000526020600020905b815481529060010190602001808311620003b957829003601f168201915b5050505050905090565b6009546000906001600160a01b0316330362000404575060131936013560601c90565b503390565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156200044a576200044a62000409565b604052919050565b600082601f8301126200046457600080fd5b81516001600160401b0381111562000480576200048062000409565b602062000496601f8301601f191682016200041f565b8281528582848701011115620004ab57600080fd5b60005b83811015620004cb578581018301518282018401528201620004ae565b506000928101909101919091529392505050565b80516001600160a01b0381168114620004f757600080fd5b919050565b80516001600160401b0381168114620004f757600080fd5b6000606082840312156200052757600080fd5b604051606081016001600160401b03811182821017156200054c576200054c62000409565b6040529050806200055d83620004df565b81526200056d60208401620004df565b6020820152604083015161ffff811681146200058857600080fd5b6040919091015292915050565b60008060008060008060008060008060006101a08c8e031215620005b857600080fd5b8b516001600160401b03811115620005cf57600080fd5b620005dd8e828f0162000452565b60208e0151909c5090506001600160401b03811115620005fc57600080fd5b6200060a8e828f0162000452565b9a505060408c0151985060608c015197506200062960808d01620004df565b96506200063960a08d01620004df565b60c08d01519096506001600160401b038111156200065657600080fd5b620006648e828f0162000452565b9550506200067560e08d01620004df565b9350620006866101008d01620004fc565b9250620006976101208d01620004df565b9150620006a98d6101408e0162000514565b90509295989b509295989b9093969950565b600181811c90821680620006d057607f821691505b602082108103620006f157634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000747576000816000526020600020601f850160051c81016020861015620007225750805b601f850160051c820191505b8181101562000743578281556001016200072e565b5050505b505050565b81516001600160401b0381111562000768576200076862000409565b6200078081620007798454620006bb565b84620006f7565b602080601f831160018114620007b857600084156200079f5750858301515b600019600386901b1c1916600185901b17855562000743565b600085815260208120601f198616915b82811015620007e957888601518255948401946001909101908401620007c8565b5085821015620008085787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516101005161012051615bc7620008e6600039600081816106bb01528181611c6201528181612690015281816126ff01528181612dc20152818161406501526142f5015260008181610be401528181610c5d0152818161139d0152818161193b0152818161197801528181611c8c01528181612d6e01528181612d9d01528181612dee01526140440152600081816109e8015281816119d3015261275e01526000611a0001526000611a350152600081816113d301526114150152615bc76000f3fe6080604052600436106103fa5760003560e01c80637035bf18116102135780639d31d92f11610123578063da742228116100ab578063f1e331151161007a578063f1e3311514610d7d578063f2fde38b14610d9d578063f6e76aa314610dbd578063fb38e00b14610dd0578063ffbafdfe14610df057600080fd5b8063da74222814610cbf578063e985e9c514610cdf578063ecb3197b14610d28578063ef90084814610d3b57600080fd5b8063b3ab15fb116100f2578063b3ab15fb14610c0b578063b88d4fde14610c2b578063b9c3a81814610c4b578063c87b56dd14610c7f578063d48ed40614610c9f57600080fd5b80639d31d92f14610b795780639d78325d14610b99578063a22cb46514610baf578063a2309ff814610bcf57600080fd5b806388a7ca5c116101a6578063950fca2911610175578063950fca2914610ae457806395d89b4114610b04578063969e447414610b1957806397b03b5714610b395780639ab06fcb14610b5957600080fd5b806388a7ca5c14610a0a5780638a19c8bc14610a2a5780638c65c81f14610a3f5780638da5cb5b14610ac657600080fd5b80637b04a2d0116101e25780637b04a2d01461095d57806382367b2d1461099657806384ea048a146109b657806385f2aef2146109d657600080fd5b80637035bf18146108f357806370a0823114610908578063715018a614610928578063745a41bc1461093d57600080fd5b806330adf81f1161030e57806351830227116102a1578063570ca73511610270578063570ca73514610853578063572b6c05146108715780635d81f3ec146108a05780636352211e146108b35780636f0aa387146108d357600080fd5b806351830227146107a257806354214f69146107bc57806355d1be4c146107d457806355f804b31461083357600080fd5b80633b2bcbf1116102dd5780633b2bcbf11461071b57806342842e0e1461074257806342966c681461076257806342f6487a1461078257600080fd5b806330adf81f1461067557806333039d3d146106a95780633644e515146106dd5780633b242439146106f257600080fd5b806313c530d0116103915780631fe543e3116103605780631fe543e3146105b657806323b872dd146105d65780632a55205a146105f65780632e1a7d4d146106355780632fbba1151461065557600080fd5b806313c530d01461054c578063141a468c1461056c57806318160ddd1461058c5780631a2832e8146105a157600080fd5b8063081812fc116103cd578063081812fc14610498578063095ea7b3146104d057806309c1ba2e146104f05780630b747d911461052857600080fd5b806301aade7b146103ff57806301ffc9a71461042157806302fa7c471461045657806306fdde0314610476575b600080fd5b34801561040b57600080fd5b5061041f61041a366004614af6565b610e10565b005b34801561042d57600080fd5b5061044161043c366004614b54565b610edd565b60405190151581526020015b60405180910390f35b34801561046257600080fd5b5061041f610471366004614b86565b610eee565b34801561048257600080fd5b5061048b610f4e565b60405161044d9190614c1b565b3480156104a457600080fd5b506104b86104b3366004614c2e565b610fe0565b6040516001600160a01b03909116815260200161044d565b3480156104dc57600080fd5b5061041f6104eb366004614c47565b611007565b3480156104fc57600080fd5b50601a54610510906001600160401b031681565b6040516001600160401b03909116815260200161044d565b34801561053457600080fd5b5061053e60155481565b60405190815260200161044d565b34801561055857600080fd5b5061041f610567366004614c87565b61112e565b34801561057857600080fd5b5061053e610587366004614c2e565b611324565b34801561059857600080fd5b5061053e61138d565b3480156105ad57600080fd5b50600e5461053e565b3480156105c257600080fd5b5061041f6105d1366004614cfd565b6113c8565b3480156105e257600080fd5b5061041f6105f1366004614d9e565b611450565b34801561060257600080fd5b50610616610611366004614ddf565b611488565b604080516001600160a01b03909316835260208301919091520161044d565b34801561064157600080fd5b5061041f610650366004614c2e565b611536565b34801561066157600080fd5b5061041f610670366004614c2e565b6118ac565b34801561068157600080fd5b5061053e7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad81565b3480156106b557600080fd5b5061053e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106e957600080fd5b5061053e6119fb565b3480156106fe57600080fd5b5061070861271081565b60405161ffff909116815260200161044d565b34801561072757600080fd5b50601a546104b890600160401b90046001600160a01b031681565b34801561074e57600080fd5b5061041f61075d366004614d9e565b611a5b565b34801561076e57600080fd5b5061041f61077d366004614c2e565b611a76565b34801561078e57600080fd5b506014546104b8906001600160a01b031681565b3480156107ae57600080fd5b506016546104419060ff1681565b3480156107c857600080fd5b5060165460ff16610441565b3480156107e057600080fd5b50601854601954610809916001600160a01b039081169190811690600160a01b900461ffff1683565b604080516001600160a01b03948516815293909216602084015261ffff169082015260600161044d565b34801561083f57600080fd5b5061041f61084e366004614af6565b611a97565b34801561085f57600080fd5b506011546001600160a01b03166104b8565b34801561087d57600080fd5b5061044161088c366004614e01565b6009546001600160a01b0391821691161490565b61041f6108ae366004614e73565b611b92565b3480156108bf57600080fd5b506104b86108ce366004614c2e565b611c00565b3480156108df57600080fd5b5061041f6108ee366004614f13565b611c60565b3480156108ff57600080fd5b5061048b611df4565b34801561091457600080fd5b5061053e610923366004614e01565b611e82565b34801561093457600080fd5b5061041f611f08565b34801561094957600080fd5b5061041f610958366004614f85565b611f1c565b34801561096957600080fd5b5061097d610978366004615028565b61202e565b6040516001600160e01b0319909116815260200161044d565b3480156109a257600080fd5b5061041f6109b1366004614ddf565b612244565b3480156109c257600080fd5b5061041f6109d1366004615083565b612337565b3480156109e257600080fd5b506104b87f000000000000000000000000000000000000000000000000000000000000000081565b348015610a1657600080fd5b5061097d610a253660046150f2565b612364565b348015610a3657600080fd5b5061053e61258c565b348015610a4b57600080fd5b50610ab2610a5a366004614c2e565b6013602052600090815260409020600181015460028201546003830154600484015460058501546006860154600790960154949593949293919260ff90911691906001600160401b0380821691600160401b90041688565b60405161044d98979695949392919061517a565b348015610ad257600080fd5b50600b546001600160a01b03166104b8565b348015610af057600080fd5b5061041f610aff366004614c2e565b612604565b348015610b1057600080fd5b5061048b612783565b348015610b2557600080fd5b5061053e610b343660046151e5565b612792565b348015610b4557600080fd5b5061041f610b54366004614ddf565b612848565b348015610b6557600080fd5b5061041f610b74366004614e01565b612931565b348015610b8557600080fd5b5061041f610b94366004615220565b6129fc565b348015610ba557600080fd5b5061053e60125481565b348015610bbb57600080fd5b5061041f610bca36600461525a565b612bfa565b348015610bdb57600080fd5b50600e54600f547f000000000000000000000000000000000000000000000000000000000000000090030161053e565b348015610c1757600080fd5b5061041f610c26366004614e01565b612c0c565b348015610c3757600080fd5b5061041f610c46366004615288565b612c8a565b348015610c5757600080fd5b5061053e7f000000000000000000000000000000000000000000000000000000000000000081565b348015610c8b57600080fd5b5061048b610c9a366004614c2e565b612cc3565b348015610cab57600080fd5b5061041f610cba366004615345565b612e92565b348015610ccb57600080fd5b5061041f610cda366004614e01565b612ef3565b348015610ceb57600080fd5b50610441610cfa366004615394565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b61041f610d363660046153c2565b612f45565b348015610d4757600080fd5b5061053e610d56366004614c47565b60009081526013602090815260408083206001600160a01b03949094168352929052205490565b348015610d8957600080fd5b5061041f610d98366004614ddf565b612f5b565b348015610da957600080fd5b5061041f610db8366004614e01565b613044565b61041f610dcb366004615401565b6130ba565b348015610ddc57600080fd5b5061041f610deb366004614ddf565b613106565b348015610dfc57600080fd5b5061041f610e0b366004615473565b6131ef565b610e18613305565b6001600160a01b0316610e336011546001600160a01b031690565b6001600160a01b03161480610e715750610e4b613305565b6001600160a01b0316610e66600b546001600160a01b031690565b6001600160a01b0316145b610e965760405162461bcd60e51b8152600401610e8d9061549f565b60405180910390fd5b6017610ea28282615572565b507f1d7696984a6c8e76fa7d719b93812fa99fec684deb7fef436692056e4c4aab8981604051610ed29190614c1b565b60405180910390a150565b6000610ee882613314565b92915050565b610ef6613339565b610f0082826133b2565b604080516001600160a01b03841681526001600160601b03831660208201527fae1d656a1268648b04ffa79c1416f05879338ae295aae3234d8db217356a1c62910160405180910390a15050565b606060028054610f5d906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610f89906154f0565b8015610fd65780601f10610fab57610100808354040283529160200191610fd6565b820191906000526020600020905b815481529060010190602001808311610fb957829003601f168201915b5050505050905090565b6000610feb826134af565b506000908152600660205260409020546001600160a01b031690565b600061101282611c00565b9050806001600160a01b0316836001600160a01b03160361107f5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610e8d565b806001600160a01b0316611091613305565b6001600160a01b031614806110ad57506110ad81610cfa613305565b61111f5760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610e8d565b611129838361350e565b505050565b611136613305565b6001600160a01b03166111516011546001600160a01b031690565b6001600160a01b0316148061118f5750611169613305565b6001600160a01b0316611184600b546001600160a01b031690565b6001600160a01b0316145b6111ab5760405162461bcd60e51b8152600401610e8d9061549f565b818110156111cc5760405163b7d0949760e01b815260040160405180910390fd5b601254600090815260136020526040902060070154600160401b90046001600160401b03168210156112115760405163b7d0949760e01b815260040160405180910390fd5b60006013600060126000815461122690615647565b918290555081526020810191909152604001600020600581018054919250899160ff19166001838181111561125d5761125d615164565b021790555060018082018890556002820187905560048201869055600682018590556007820180546001600160401b03858116600160401b026001600160801b031990921690871617179055601254907f2f97fd490e935512c57b9c40169523f1fffb4291d075d10c2de74783f22ef95c908a908111156112e0576112e0615164565b60408051918252602082018b90528101899052606081018890526080810187905260a0810186905260c0810185905260e00160405180910390a25050505050505050565b6000818152600460205260408120546001600160a01b031661137a5760405162461bcd60e51b815260206004820152600f60248201526e21554e4b4e4f574e5f544f4b454e2160881b6044820152606401610e8d565b5060009081526008602052604090205490565b60006010546113c2600e54600f547f000000000000000000000000000000000000000000000000000000000000000090030190565b03905090565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146114425760405163073e64fd60e21b81523360048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610e8d565b61144c828261357c565b5050565b61146161145b613305565b8261359f565b61147d5760405162461bcd60e51b8152600401610e8d90615660565b61112983838361361d565b60008281526001602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916114fd5750604080518082019091526000546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101516000906127109061151c906001600160601b0316876156ae565b61152691906156db565b91519350909150505b9250929050565b61153e613305565b6001600160a01b03166115596011546001600160a01b031690565b6001600160a01b031614806115975750611571613305565b6001600160a01b031661158c600b546001600160a01b031690565b6001600160a01b0316145b6115b35760405162461bcd60e51b8152600401610e8d9061549f565b6002600a54036116055760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e8d565b6002600a55806001810161169a576014546001600160a01b031615611695576014546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561166c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169091906156ef565b611697565b475b90505b601954600090612710906116b990600160a01b900461ffff16846156ae565b6116c391906156db565b905060006116d18284615708565b6014549091506001600160a01b03166117ac576018546040516000916001600160a01b03169084908381818185875af1925050503d8060008114611731576040519150601f19603f3d011682016040523d82523d6000602084013e611736565b606091505b505090508061174457600080fd5b6019546040516001600160a01b03909116908390600081818185875af1925050503d8060008114611791576040519150601f19603f3d011682016040523d82523d6000602084013e611796565b606091505b505080915050806117a657600080fd5b506118a1565b60145460185460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810185905291169063a9059cbb906044016020604051808303816000875af1158015611801573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611825919061571b565b5060145460195460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810184905291169063a9059cbb906044016020604051808303816000875af115801561187b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189f919061571b565b505b50506001600a555050565b6118b4613305565b6001600160a01b03166118cf6011546001600160a01b031690565b6001600160a01b0316148061190d57506118e7613305565b6001600160a01b0316611902600b546001600160a01b031690565b6001600160a01b0316145b6119295760405162461bcd60e51b8152600401610e8d9061549f565b600019810361196257600e5461195f907f0000000000000000000000000000000000000000000000000000000000000000615708565b90505b8061196c600e5490565b6119769190615738565b7f000000000000000000000000000000000000000000000000000000000000000010156119b657604051636ee3e45960e11b815260040160405180910390fd5b80600e60008282546119c89190615738565b909155506119f890507f000000000000000000000000000000000000000000000000000000000000000082613628565b50565b6000467f00000000000000000000000000000000000000000000000000000000000000008114611a3357611a2e8161365f565b611a55565b7f00000000000000000000000000000000000000000000000000000000000000005b91505090565b61112983838360405180602001604052806000815250612c8a565b611a7f8161370b565b60108054906000611a8f83615647565b919050555050565b611a9f613305565b6001600160a01b0316611aba6011546001600160a01b031690565b6001600160a01b03161480611af85750611ad2613305565b6001600160a01b0316611aed600b546001600160a01b031690565b6001600160a01b0316145b611b145760405162461bcd60e51b8152600401610e8d9061549f565b6000815111611b565760405162461bcd60e51b815260206004820152600e60248201526d77726f6e6720626173652075726960901b6044820152606401610e8d565b600c611b628282615572565b507f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad81604051610ed29190614c1b565b611ba8611b9f89876156ae565b8585858561373b565b611bf4611bb3613305565b60008c8c808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508e92508d91508c90508b6137df565b50505050505050505050565b6000818152600460205260408120546001600160a01b031680610ee85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b7f0000000000000000000000000000000000000000000000000000000000000000611cb1600e54600f547f000000000000000000000000000000000000000000000000000000000000000090030190565b1015611cd0576040516303ba630160e01b815260040160405180910390fd5b611cd8613305565b6001600160a01b0316611cf36011546001600160a01b031690565b6001600160a01b03161480611d315750611d0b613305565b6001600160a01b0316611d26600b546001600160a01b031690565b6001600160a01b0316145b611d4d5760405162461bcd60e51b8152600401610e8d9061549f565b601a546040516305d3b1d360e41b8152600481018590526001600160401b038216602482015261ffff8416604482015263ffffffff8316606482015260016084820152600160401b9091046001600160a01b031690635d3b1d309060a4016020604051808303816000875af1158015611dca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dee91906156ef565b50505050565b60178054611e01906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054611e2d906154f0565b8015611e7a5780601f10611e4f57610100808354040283529160200191611e7a565b820191906000526020600020905b815481529060010190602001808311611e5d57829003601f168201915b505050505081565b60006001600160a01b038216611eec5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610e8d565b506001600160a01b031660009081526005602052604090205490565b611f10613339565b611f1a60006139c5565b565b42821015611f6c5760405162461bcd60e51b815260206004820152601960248201527f215045524d49545f444541444c494e455f4558504952454421000000000000006044820152606401610e8d565b600083815260086020526040812054611f89908690869086612792565b90506000611f978284613a17565b5090506001600160a01b03811615801590611fb75750611fb7818661359f565b80611fd05750611fd0611fc986611c00565b8385613a59565b61201c5760405162461bcd60e51b815260206004820152601a60248201527f21494e56414c49445f5045524d49545f5349474e4154555245210000000000006044820152606401610e8d565b612026868661350e565b505050505050565b6014546000906001600160a01b031633146120825760405162461bcd60e51b81526020600482015260146024820152731bdb9b1e48115490cc4ccd8cc81c185e5b595b9d60621b6044820152606401610e8d565b7f71d859275b482dfe1e2d14bfd2863dbe5cc9914143fea269841eb035fd6afaf533868686866040516120b9959493929190615774565b60405180910390a160006120d060048285876157b3565b6120d9916157dd565b905060006120ea84600481886157b3565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050506001600160e01b0319821663134ce68560e01b0161217357600080600080848060200190518101906121539190615818565b935093509350935061216a8b600086868686613b9b565b5050505061222f565b630918955d60e01b6001600160e01b03198316016121cb576000806000806000858060200190518101906121a79190615857565b945094509450945094506121c18c600087878787876137df565b505050505061222f565b60405162461bcd60e51b815260206004820152603360248201527f6f6e417070726f76616c52656365697665643a2066756e6374696f6e2073656c6044820152721958dd1bdc881b9bdd081cdd5c1c1bdc9d1959606a1b6064820152608401610e8d565b506307b04a2d60e41b9150505b949350505050565b818060125410156122685760405163ed6b05a360e01b815260040160405180910390fd5b612270613305565b6001600160a01b031661228b6011546001600160a01b031690565b6001600160a01b031614806122c957506122a3613305565b6001600160a01b03166122be600b546001600160a01b031690565b6001600160a01b0316145b6122e55760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060048101859055915184815285917f945c1c4e99aa89f648fbfe3df471b916f719e16d960fcec0737d4d56bd69683891015b60405180910390a250505050565b612344611b9f89876156ae565b61235a61234f613305565b60008a8a8a8a613b9b565b5050505050505050565b6014546000906001600160a01b031633146123b85760405162461bcd60e51b81526020600482015260146024820152731bdb9b1e48115490cc4ccd8cc81c185e5b595b9d60621b6044820152606401610e8d565b7fa10ea941849680df7289f12b45394b2f603bb88bfd7346374c8e6dbb8fd27fb83387878787876040516123f196959493929190615917565b60405180910390a1600061240860048285876157b3565b612411916157dd565b905036600061242385600481896157b3565b909250905063134ce68560e01b6001600160e01b031984160161249b576000808080612451858701876153c2565b93509350935093508a818561246691906156ae565b146124835760405162461bcd60e51b8152600401610e8d90615953565b6124928c600186868686613b9b565b50505050612577565b630918955d60e01b6001600160e01b0319841601612513576000808080806124c586880188615995565b945094509450945094508b81856124dc91906156ae565b146124f95760405162461bcd60e51b8152600401610e8d90615953565b6125098d600187878787876137df565b5050505050612577565b60405162461bcd60e51b815260206004820152603360248201527f6f6e5472616e7366657252656365697665643a2066756e6374696f6e2073656c6044820152721958dd1bdc881b9bdd081cdd5c1c1bdc9d1959606a1b6064820152608401610e8d565b50632229f29760e21b98975050505050505050565b60008060015b60125481116125fb5760008181526013602052604090206007810154909250426001600160401b03909116118015906125de57506007820154600160401b90046001600160401b031642105b156125e95792915050565b806125f381615647565b915050612592565b50600091505090565b61260c613305565b6001600160a01b03166126276011546001600160a01b031690565b6001600160a01b03161480612665575061263f613305565b6001600160a01b031661265a600b546001600160a01b031690565b6001600160a01b0316145b6126815760405162461bcd60e51b8152600401610e8d9061549f565b60001981036126b15750600f547f0000000000000000000000000000000000000000000000000000000000000000035b601254600090815260136020526040902060070154600160401b90046001600160401b03164210156126f657604051632e25514d60e11b815260040160405180910390fd5b80612722600f547f00000000000000000000000000000000000000000000000000000000000000000390565b101561274157604051630a5b751b60e41b815260040160405180910390fd5b80600f60008282546127539190615738565b909155506119f890507f000000000000000000000000000000000000000000000000000000000000000082613d4d565b606060038054610f5d906154f0565b600061283f61279f6119fb565b604080517f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad6020808301919091526001600160a01b038a1682840152606082018990526080820188905260a08083018890528351808403909101815260c08301845280519082012061190160f01b60e084015260e28301949094526101028083019490945282518083039094018452610122909101909152815191012090565b95945050505050565b8180601254101561286c5760405163ed6b05a360e01b815260040160405180910390fd5b612874613305565b6001600160a01b031661288f6011546001600160a01b031690565b6001600160a01b031614806128cd57506128a7613305565b6001600160a01b03166128c2600b546001600160a01b031690565b6001600160a01b0316145b6128e95760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060028101859055915184815285917fc37cc9c3c37fdcacbe05156c2f68f96e3d3ecec5a381a8929651bf7a317f0d1c9101612329565b612939613305565b6001600160a01b03166129546011546001600160a01b031690565b6001600160a01b03161480612992575061296c613305565b6001600160a01b0316612987600b546001600160a01b031690565b6001600160a01b0316145b6129ae5760405162461bcd60e51b8152600401610e8d9061549f565b601480546001600160a01b0319166001600160a01b0383169081179091556040519081527f424cf801e48c82bd3bcec24e3c7b5912fbdd079dad1e9137321af112db07381f90602001610ed2565b82806012541015612a205760405163ed6b05a360e01b815260040160405180910390fd5b612a28613305565b6001600160a01b0316612a436011546001600160a01b031690565b6001600160a01b03161480612a815750612a5b613305565b6001600160a01b0316612a76600b546001600160a01b031690565b6001600160a01b0316145b612a9d5760405162461bcd60e51b8152600401610e8d9061549f565b82821015612abe5760405163b7d0949760e01b815260040160405180910390fd5b600084815260136020526040902060125485108015612b0757508260136000612ae8886001615738565b81526020810191909152604001600020600701546001600160401b0316105b15612b255760405163b7d0949760e01b815260040160405180910390fd5b846001108015612b66575060136000612b3f600188615708565b8152602081019190915260400160002060070154600160401b90046001600160401b031684105b15612b845760405163b7d0949760e01b815260040160405180910390fd5b6007810180546001600160401b03858116600160401b026001600160801b03199092169087161717905560405185907f2ce088ba9de5c469723f27edb3150dd5b001a016d992fed4a7e1d0c1cc39137290612beb9087908790918252602082015260400190565b60405180910390a25050505050565b61144c612c05613305565b8383613d84565b612c14613339565b6001600160a01b038116612c815760405162461bcd60e51b815260206004820152602e60248201527f4e656f77697a4552433732313a206e6577206f70657261746f7220697320746860448201526d65207a65726f206164647265737360901b6064820152608401610e8d565b6119f881613e52565b612c9b612c95613305565b8361359f565b612cb75760405162461bcd60e51b8152600401610e8d90615660565b611dee84848484613ea0565b6060612cce826134af565b60165460ff16612d6a5760178054612ce5906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054612d11906154f0565b8015612d5e5780601f10612d3357610100808354040283529160200191612d5e565b820191906000526020600020905b815481529060010190602001808311612d4157829003601f168201915b50505050509050919050565b60007f0000000000000000000000000000000000000000000000000000000000000000831015612d9b575081612e34565b7f0000000000000000000000000000000000000000000000000000000000000000612de6817f0000000000000000000000000000000000000000000000000000000000000000615708565b601554612e137f000000000000000000000000000000000000000000000000000000000000000087615708565b612e1d9190615738565b612e2791906159ff565b612e319190615738565b90505b6000600c8054612e43906154f0565b905011612e5f5760405180602001604052806000815250612e8b565b600c612e6a82613ed3565b604051602001612e7b929190615a13565b6040516020818303038152906040525b9392505050565b6040516bffffffffffffffffffffffff19606083901b166020820152600090603401604051602081830303815290604052805190602001209050612ed7848483613fd3565b611dee576040516227b15560e01b815260040160405180910390fd5b612efb613339565b600980546001600160a01b0319166001600160a01b0383169081179091556040517fffd948da7ce0ac541cf3790b301b0df6af19e474ed095744d1460a7ea6b7d15390600090a250565b611dee612f50613305565b600086868686613b9b565b81806012541015612f7f5760405163ed6b05a360e01b815260040160405180910390fd5b612f87613305565b6001600160a01b0316612fa26011546001600160a01b031690565b6001600160a01b03161480612fe05750612fba613305565b6001600160a01b0316612fd5600b546001600160a01b031690565b6001600160a01b0316145b612ffc5760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060068101859055915184815285917f9ff79792a92b66fee090acb66e07837a2edb31ee6b9780fa551fd04b79dffcd29101612329565b61304c613339565b6001600160a01b0381166130b15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e8d565b6119f8816139c5565b6120266130c5613305565b60008888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250899150889050876137df565b8180601254101561312a5760405163ed6b05a360e01b815260040160405180910390fd5b613132613305565b6001600160a01b031661314d6011546001600160a01b031690565b6001600160a01b0316148061318b5750613165613305565b6001600160a01b0316613180600b546001600160a01b031690565b6001600160a01b0316145b6131a75760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060018101859055915184815285917f258fa6ef7a3f3b3f76e4871e78d8e046e00bcf3f3e2662a58b3da774a2a74f399101612329565b818060125410156132135760405163ed6b05a360e01b815260040160405180910390fd5b61321b613305565b6001600160a01b03166132366011546001600160a01b031690565b6001600160a01b03161480613274575061324e613305565b6001600160a01b0316613269600b546001600160a01b031690565b6001600160a01b0316145b6132905760405162461bcd60e51b8152600401610e8d9061549f565b600083815260136020526040902060058101805484919060ff1916600183818111156132be576132be615164565b0217905550837f210cbb60935822c957f36bfad9f082e34516b470d608565d6e21abfd2d771beb8460018111156132f7576132f7615164565b604051908152602001612329565b600061330f613fe9565b905090565b60006001600160e01b03198216635604e22560e01b1480610ee85750610ee882614010565b613341613305565b6001600160a01b031661335c600b546001600160a01b031690565b6001600160a01b031614611f1a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e8d565b6127106001600160601b03821611156134205760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610e8d565b6001600160a01b0382166134765760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610e8d565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600055565b6000818152600460205260409020546001600160a01b03166119f85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b600081815260066020526040902080546001600160a01b0319166001600160a01b038416908117909155819061354382611c00565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b61144c8160008151811061359257613592615a9a565b602002602001015161401b565b6000806135ab83611c00565b9050806001600160a01b0316846001600160a01b031614806135f257506001600160a01b0380821660009081526007602090815260408083209388168352929052205460ff165b8061223c5750836001600160a01b031661360b84610fe0565b6001600160a01b031614949350505050565b6111298383836140cf565b600081600e546136389190615708565b9050805b6136468383615738565b811015611dee5761365784826140e3565b60010161363c565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61368a610f4e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b61371661145b613305565b6137325760405162461bcd60e51b8152600401610e8d90615660565b6119f8816140fd565b6014546001600160a01b031663d505accf613754613305565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018890526064810187905260ff8616608482015260a4810185905260c4810184905260e401600060405180830381600087803b1580156137c057600080fd5b505af11580156137d4573d6000803e3d6000fd5b505050505050505050565b60008381526013602052604090206012548491908211156138135760405163363a51ef60e01b815260040160405180910390fd5b60078101546001600160401b0316421015613841576040516323a71b8760e21b815260040160405180910390fd5b600781015442600160401b9091046001600160401b03161161387657604051636b5fd31b60e01b815260040160405180910390fd5b600085815260136020526040812060050154869160ff909116908160018111156138a2576138a2615164565b146138c057604051630a7bec6d60e21b815260040160405180910390fd5b60008781526013602052604090206014546001600160a01b038881169116146139225760405162461bcd60e51b81526020600482015260146024820152731c185e5b595b9d081a5cc8191a5999995c995b9d60621b6044820152606401610e8d565b806004015486146139705760405162461bcd60e51b81526020600482015260186024820152771c9bdd5b99081c1c9a58d9481a5cc8191a5999995c995b9d60421b6044820152606401610e8d565b60008881526013602052604090206006015461398e908b908e612e92565b8a6139ac576139ac8c8a83600401546139a791906156ae565b614106565b6139b7888d8b614242565b505050505050505050505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000808251604103613a4d5760208301516040840151606085015160001a613a41878285856143a3565b9450945050505061152f565b5060009050600261152f565b6000806000613a688585613a17565b90925090506000816004811115613a8157613a81615164565b148015613a9f5750856001600160a01b0316826001600160a01b0316145b15613aaf57600192505050612e8b565b600080876001600160a01b0316631626ba7e60e01b8888604051602401613ad7929190615ab0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613b159190615ac9565b600060405180830381855afa9150503d8060008114613b50576040519150601f19603f3d011682016040523d82523d6000602084013e613b55565b606091505b5091509150818015613b68575080516020145b8015613b8f57508051630b135d3f60e11b90613b8d90830160209081019084016156ef565b145b98975050505050505050565b6000838152601360205260409020601254849190821115613bcf5760405163363a51ef60e01b815260040160405180910390fd5b60078101546001600160401b0316421015613bfd576040516323a71b8760e21b815260040160405180910390fd5b600781015442600160401b9091046001600160401b031611613c3257604051636b5fd31b60e01b815260040160405180910390fd5b84600160008281526013602052604090206005015460ff166001811115613c5b57613c5b615164565b14613c7957604051637002ac7160e11b815260040160405180910390fd5b60008681526013602052604090206014546001600160a01b03878116911614613cdb5760405162461bcd60e51b81526020600482015260146024820152731c185e5b595b9d081a5cc8191a5999995c995b9d60621b6044820152606401610e8d565b80600401548514613d295760405162461bcd60e51b81526020600482015260186024820152771c9bdd5b99081c1c9a58d9481a5cc8191a5999995c995b9d60421b6044820152606401610e8d565b88613d4257613d428a8983600401546139a791906156ae565b611bf4878b8a614242565b600081600f54613d5d9190615708565b9050805b613d6b8383615738565b811015611dee57613d7c84826140e3565b600101613d61565b816001600160a01b0316836001600160a01b031603613de55760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610e8d565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b601180546001600160a01b0319166001600160a01b0383169081179091556040519081527fda12ee837e6978172aaf54b16145ffe08414fd8710092ef033c71b8eb6ec189a90602001610ed2565b613eab84848461361d565b613eb784848484614490565b611dee5760405162461bcd60e51b8152600401610e8d90615ae5565b606081600003613efa5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613f245780613f0e81615647565b9150613f1d9050600a836156db565b9150613efe565b6000816001600160401b03811115613f3e57613f3e614a59565b6040519080825280601f01601f191660200182016040528015613f68576020820181803683370190505b5090505b841561223c57613f7d600183615708565b9150613f8a600a866159ff565b613f95906030615738565b60f81b818381518110613faa57613faa615a9a565b60200101906001600160f81b031916908160001a905350613fcc600a866156db565b9450613f6c565b600082613fe08584614595565b14949350505050565b6009546000906001600160a01b0316330361400b575060131936013560601c90565b503390565b6000610ee8826145d8565b60165460ff161561403f5760405163a89ac15160e01b815260040160405180910390fd5b6140897f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000615708565b61409390826159ff565b6015556016805460ff191660011790556040517fe2a7169cedebe39671840370ae19ca4fc41be6191d4c77f174f189a4d8cd08c890600090a150565b6140d881614618565b611129838383614632565b61144c8282604051806020016040528060008152506147ce565b6119f881614801565b6014546001600160a01b031615614221576014546040516370a0823160e01b81526001600160a01b038481166004830152839216906370a0823190602401602060405180830381865afa158015614161573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418591906156ef565b10156141a4576040516302b1b38b60e61b815260040160405180910390fd5b6014546040516323b872dd60e01b81526001600160a01b03848116600483015230602483015260448201849052909116906323b872dd906064016020604051808303816000875af11580156141fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611129919061571b565b8034101561144c57604051634a531cfd60e01b815260040160405180910390fd5b60008381526013602090815260408083206001600160a01b03861684529182905290912054614272908390615738565b816001015410156142a85760405163c86a5f3560e01b8152600481018590526001600160a01b0384166024820152604401610e8d565b60125484141580156142cc57508181600301546142c59190615738565b8160020154105b156142ec57604051626dc22f60e91b815260048101859052602401610e8d565b81614318600f547f00000000000000000000000000000000000000000000000000000000000000000390565b101561433757604051630a5b751b60e41b815260040160405180910390fd5b6001600160a01b0383166000908152602082905260408120805484929061435f908490615738565b925050819055508181600301600082825461437a9190615738565b9250508190555081600f60008282546143939190615738565b90915550611dee90508383613d4d565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156143da5750600090506003614487565b8460ff16601b141580156143f257508460ff16601c14155b156144035750600090506004614487565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614457573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661448057600060019250925050614487565b9150600090505b94509492505050565b60006001600160a01b0384163b1561458d57836001600160a01b031663150b7a026144b9613305565b8786866040518563ffffffff1660e01b81526004016144db9493929190615b37565b6020604051808303816000875af1925050508015614516575060408051601f3d908101601f1916820190925261451391810190615b74565b60015b614573573d808015614544576040519150601f19603f3d011682016040523d82523d6000602084013e614549565b606091505b50805160000361456b5760405162461bcd60e51b8152600401610e8d90615ae5565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061223c565b50600161223c565b600081815b84518110156145d0576145c6828683815181106145b9576145b9615a9a565b602002602001015161481b565b915060010161459a565b509392505050565b60006001600160e01b031982166380ac58cd60e01b148061460957506001600160e01b03198216635b5e139f60e01b145b80610ee85750610ee882614847565b6000818152600860205260408120805491611a8f83615647565b826001600160a01b031661464582611c00565b6001600160a01b0316146146a95760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610e8d565b6001600160a01b03821661470b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610e8d565b61471660008261350e565b6001600160a01b038316600090815260056020526040812080546001929061473f908490615708565b90915550506001600160a01b038216600090815260056020526040812080546001929061476d908490615738565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6147d8838361487c565b6147e56000848484614490565b6111295760405162461bcd60e51b8152600401610e8d90615ae5565b61480a816149be565b600090815260016020526040812055565b6000818310614837576000828152602084905260409020612e8b565b5060009182526020526040902090565b60006001600160e01b0319821663152a902d60e11b1480610ee857506301ffc9a760e01b6001600160e01b0319831614610ee8565b6001600160a01b0382166148d25760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610e8d565b6000818152600460205260409020546001600160a01b0316156149375760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6001600160a01b0382166000908152600560205260408120805460019290614960908490615738565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006149c982611c00565b90506149d660008361350e565b6001600160a01b03811660009081526005602052604081208054600192906149ff908490615708565b909155505060008281526004602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614a9757614a97614a59565b604052919050565b60006001600160401b03831115614ab857614ab8614a59565b614acb601f8401601f1916602001614a6f565b9050828152838383011115614adf57600080fd5b828260208301376000602084830101529392505050565b600060208284031215614b0857600080fd5b81356001600160401b03811115614b1e57600080fd5b8201601f81018413614b2f57600080fd5b61223c84823560208401614a9f565b6001600160e01b0319811681146119f857600080fd5b600060208284031215614b6657600080fd5b8135612e8b81614b3e565b6001600160a01b03811681146119f857600080fd5b60008060408385031215614b9957600080fd5b8235614ba481614b71565b915060208301356001600160601b0381168114614bc057600080fd5b809150509250929050565b60005b83811015614be6578181015183820152602001614bce565b50506000910152565b60008151808452614c07816020860160208601614bcb565b601f01601f19169290920160200192915050565b602081526000612e8b6020830184614bef565b600060208284031215614c4057600080fd5b5035919050565b60008060408385031215614c5a57600080fd5b8235614c6581614b71565b946020939093013593505050565b803560028110614c8257600080fd5b919050565b600080600080600080600060e0888a031215614ca257600080fd5b614cab88614c73565b9960208901359950604089013598606081013598506080810135975060a0810135965060c00135945092505050565b60006001600160401b03821115614cf357614cf3614a59565b5060051b60200190565b60008060408385031215614d1057600080fd5b823591506020808401356001600160401b03811115614d2e57600080fd5b8401601f81018613614d3f57600080fd5b8035614d52614d4d82614cda565b614a6f565b81815260059190911b82018301908381019088831115614d7157600080fd5b928401925b82841015614d8f57833582529284019290840190614d76565b80955050505050509250929050565b600080600060608486031215614db357600080fd5b8335614dbe81614b71565b92506020840135614dce81614b71565b929592945050506040919091013590565b60008060408385031215614df257600080fd5b50508035926020909101359150565b600060208284031215614e1357600080fd5b8135612e8b81614b71565b60008083601f840112614e3057600080fd5b5081356001600160401b03811115614e4757600080fd5b6020830191508360208260051b850101111561152f57600080fd5b803560ff81168114614c8257600080fd5b6000806000806000806000806000806101208b8d031215614e9357600080fd5b8a356001600160401b03811115614ea957600080fd5b614eb58d828e01614e1e565b909b5099505060208b0135975060408b0135965060608b0135614ed781614b71565b955060808b0135945060a08b01359350614ef360c08c01614e62565b925060e08b013591506101008b013590509295989b9194979a5092959850565b600080600060608486031215614f2857600080fd5b83359250602084013561ffff81168114614f4157600080fd5b9150604084013563ffffffff81168114614f5a57600080fd5b809150509250925092565b600082601f830112614f7657600080fd5b612e8b83833560208501614a9f565b60008060008060808587031215614f9b57600080fd5b8435614fa681614b71565b9350602085013592506040850135915060608501356001600160401b03811115614fcf57600080fd5b614fdb87828801614f65565b91505092959194509250565b60008083601f840112614ff957600080fd5b5081356001600160401b0381111561501057600080fd5b60208301915083602082850101111561152f57600080fd5b6000806000806060858703121561503e57600080fd5b843561504981614b71565b93506020850135925060408501356001600160401b0381111561506b57600080fd5b61507787828801614fe7565b95989497509550505050565b600080600080600080600080610100898b0312156150a057600080fd5b883597506020890135965060408901356150b981614b71565b955060608901359450608089013593506150d560a08a01614e62565b925060c0890135915060e089013590509295985092959890939650565b60008060008060006080868803121561510a57600080fd5b853561511581614b71565b9450602086013561512581614b71565b93506040860135925060608601356001600160401b0381111561514757600080fd5b61515388828901614fe7565b969995985093965092949392505050565b634e487b7160e01b600052602160045260246000fd5b600061010082019050898252886020830152876040830152866060830152600286106151b657634e487b7160e01b600052602160045260246000fd5b608082019590955260a08101939093526001600160401b0391821660c08401521660e090910152949350505050565b600080600080608085870312156151fb57600080fd5b843561520681614b71565b966020860135965060408601359560600135945092505050565b60008060006060848603121561523557600080fd5b505081359360208301359350604090920135919050565b80151581146119f857600080fd5b6000806040838503121561526d57600080fd5b823561527881614b71565b91506020830135614bc08161524c565b6000806000806080858703121561529e57600080fd5b84356152a981614b71565b935060208501356152b981614b71565b92506040850135915060608501356001600160401b03811115614fcf57600080fd5b600082601f8301126152ec57600080fd5b813560206152fc614d4d83614cda565b8083825260208201915060208460051b87010193508684111561531e57600080fd5b602086015b8481101561533a5780358352918301918301615323565b509695505050505050565b60008060006060848603121561535a57600080fd5b83356001600160401b0381111561537057600080fd5b61537c868287016152db565b935050602084013591506040840135614f5a81614b71565b600080604083850312156153a757600080fd5b82356153b281614b71565b91506020830135614bc081614b71565b600080600080608085870312156153d857600080fd5b843593506020850135925060408501356153f181614b71565b9396929550929360600135925050565b60008060008060008060a0878903121561541a57600080fd5b86356001600160401b0381111561543057600080fd5b61543c89828a01614e1e565b9097509550506020870135935060408701359250606087013561545e81614b71565b80925050608087013590509295509295509295565b6000806040838503121561548657600080fd5b8235915061549660208401614c73565b90509250929050565b60208082526031908201527f4e656f77697a4552433732313a2063616c6c6572206973206e6f74207468652060408201527037b832b930ba37b91037b91037bbb732b960791b606082015260800190565b600181811c9082168061550457607f821691505b60208210810361552457634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611129576000816000526020600020601f850160051c810160208610156155535750805b601f850160051c820191505b818110156120265782815560010161555f565b81516001600160401b0381111561558b5761558b614a59565b61559f8161559984546154f0565b8461552a565b602080601f8311600181146155d457600084156155bc5750858301515b600019600386901b1c1916600185901b178555612026565b600085815260208120601f198616915b82811015615603578886015182559484019460019091019084016155e4565b50858210156156215787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b60006001820161565957615659615631565b5060010190565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b8082028115828204841417610ee857610ee8615631565b634e487b7160e01b600052601260045260246000fd5b6000826156ea576156ea6156c5565b500490565b60006020828403121561570157600080fd5b5051919050565b81810381811115610ee857610ee8615631565b60006020828403121561572d57600080fd5b8151612e8b8161524c565b80820180821115610ee857610ee8615631565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b03868116825285166020820152604081018490526080606082018190526000906157a8908301848661574b565b979650505050505050565b600080858511156157c357600080fd5b838611156157d057600080fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156158055780818660040360031b1b83161692505b505092915050565b8051614c8281614b71565b6000806000806080858703121561582e57600080fd5b8451935060208501519250604085015161584781614b71565b6060959095015193969295505050565b600080600080600060a0868803121561586f57600080fd5b85516001600160401b0381111561588557600080fd5b8601601f8101881361589657600080fd5b805160206158a6614d4d83614cda565b82815260059290921b8301810191818101908b8411156158c557600080fd5b938201935b838510156158e3578451825293820193908201906158ca565b8099505050808901519650505050604086015192506159046060870161580d565b9150608086015190509295509295909350565b6001600160a01b0387811682528681166020830152851660408201526060810184905260a060808201819052600090613b8f908301848661574b565b60208082526022908201527f6f6e5472616e7366657252656365697665643a20696e76616c696420616d6f756040820152611b9d60f21b606082015260800190565b600080600080600060a086880312156159ad57600080fd5b85356001600160401b038111156159c357600080fd5b6159cf888289016152db565b955050602086013593506040860135925060608601356159ee81614b71565b949793965091946080013592915050565b600082615a0e57615a0e6156c5565b500690565b6000808454615a21816154f0565b60018281168015615a395760018114615a4e57615a7d565b60ff1984168752821515830287019450615a7d565b8860005260208060002060005b85811015615a745781548a820152908401908201615a5b565b50505082870194505b505050508351615a91818360208801614bcb565b01949350505050565b634e487b7160e01b600052603260045260246000fd5b82815260406020820152600061223c6040830184614bef565b60008251615adb818460208701614bcb565b9190910192915050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615b6a90830184614bef565b9695505050505050565b600060208284031215615b8657600080fd5b8151612e8b81614b3e56fea26469706673582212202fb497ab354989fe8376313f570296e60952c6e1a03c9c7f953a822b9686986464736f6c6343000817003300000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000078a00000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000380000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909000000000000000000000000d255647b9f573916e676db77cd34c9e8bd00528a000000000000000000000000cb9440b0d963c54a6d68aa847517f2ed5311d4ba000000000000000000000000000000000000000000000000000000000000232800000000000000000000000000000000000000000000000000000000000000174561726c792052657469726564204361747320436c7562000000000000000000000000000000000000000000000000000000000000000000000000000000000445524343000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d6648797635587a50723878336355474679623575316e694d666e315268337a336a74715033693842656a6b460000000000000000000000

Deployed Bytecode

0x6080604052600436106103fa5760003560e01c80637035bf18116102135780639d31d92f11610123578063da742228116100ab578063f1e331151161007a578063f1e3311514610d7d578063f2fde38b14610d9d578063f6e76aa314610dbd578063fb38e00b14610dd0578063ffbafdfe14610df057600080fd5b8063da74222814610cbf578063e985e9c514610cdf578063ecb3197b14610d28578063ef90084814610d3b57600080fd5b8063b3ab15fb116100f2578063b3ab15fb14610c0b578063b88d4fde14610c2b578063b9c3a81814610c4b578063c87b56dd14610c7f578063d48ed40614610c9f57600080fd5b80639d31d92f14610b795780639d78325d14610b99578063a22cb46514610baf578063a2309ff814610bcf57600080fd5b806388a7ca5c116101a6578063950fca2911610175578063950fca2914610ae457806395d89b4114610b04578063969e447414610b1957806397b03b5714610b395780639ab06fcb14610b5957600080fd5b806388a7ca5c14610a0a5780638a19c8bc14610a2a5780638c65c81f14610a3f5780638da5cb5b14610ac657600080fd5b80637b04a2d0116101e25780637b04a2d01461095d57806382367b2d1461099657806384ea048a146109b657806385f2aef2146109d657600080fd5b80637035bf18146108f357806370a0823114610908578063715018a614610928578063745a41bc1461093d57600080fd5b806330adf81f1161030e57806351830227116102a1578063570ca73511610270578063570ca73514610853578063572b6c05146108715780635d81f3ec146108a05780636352211e146108b35780636f0aa387146108d357600080fd5b806351830227146107a257806354214f69146107bc57806355d1be4c146107d457806355f804b31461083357600080fd5b80633b2bcbf1116102dd5780633b2bcbf11461071b57806342842e0e1461074257806342966c681461076257806342f6487a1461078257600080fd5b806330adf81f1461067557806333039d3d146106a95780633644e515146106dd5780633b242439146106f257600080fd5b806313c530d0116103915780631fe543e3116103605780631fe543e3146105b657806323b872dd146105d65780632a55205a146105f65780632e1a7d4d146106355780632fbba1151461065557600080fd5b806313c530d01461054c578063141a468c1461056c57806318160ddd1461058c5780631a2832e8146105a157600080fd5b8063081812fc116103cd578063081812fc14610498578063095ea7b3146104d057806309c1ba2e146104f05780630b747d911461052857600080fd5b806301aade7b146103ff57806301ffc9a71461042157806302fa7c471461045657806306fdde0314610476575b600080fd5b34801561040b57600080fd5b5061041f61041a366004614af6565b610e10565b005b34801561042d57600080fd5b5061044161043c366004614b54565b610edd565b60405190151581526020015b60405180910390f35b34801561046257600080fd5b5061041f610471366004614b86565b610eee565b34801561048257600080fd5b5061048b610f4e565b60405161044d9190614c1b565b3480156104a457600080fd5b506104b86104b3366004614c2e565b610fe0565b6040516001600160a01b03909116815260200161044d565b3480156104dc57600080fd5b5061041f6104eb366004614c47565b611007565b3480156104fc57600080fd5b50601a54610510906001600160401b031681565b6040516001600160401b03909116815260200161044d565b34801561053457600080fd5b5061053e60155481565b60405190815260200161044d565b34801561055857600080fd5b5061041f610567366004614c87565b61112e565b34801561057857600080fd5b5061053e610587366004614c2e565b611324565b34801561059857600080fd5b5061053e61138d565b3480156105ad57600080fd5b50600e5461053e565b3480156105c257600080fd5b5061041f6105d1366004614cfd565b6113c8565b3480156105e257600080fd5b5061041f6105f1366004614d9e565b611450565b34801561060257600080fd5b50610616610611366004614ddf565b611488565b604080516001600160a01b03909316835260208301919091520161044d565b34801561064157600080fd5b5061041f610650366004614c2e565b611536565b34801561066157600080fd5b5061041f610670366004614c2e565b6118ac565b34801561068157600080fd5b5061053e7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad81565b3480156106b557600080fd5b5061053e7f000000000000000000000000000000000000000000000000000000000000078a81565b3480156106e957600080fd5b5061053e6119fb565b3480156106fe57600080fd5b5061070861271081565b60405161ffff909116815260200161044d565b34801561072757600080fd5b50601a546104b890600160401b90046001600160a01b031681565b34801561074e57600080fd5b5061041f61075d366004614d9e565b611a5b565b34801561076e57600080fd5b5061041f61077d366004614c2e565b611a76565b34801561078e57600080fd5b506014546104b8906001600160a01b031681565b3480156107ae57600080fd5b506016546104419060ff1681565b3480156107c857600080fd5b5060165460ff16610441565b3480156107e057600080fd5b50601854601954610809916001600160a01b039081169190811690600160a01b900461ffff1683565b604080516001600160a01b03948516815293909216602084015261ffff169082015260600161044d565b34801561083f57600080fd5b5061041f61084e366004614af6565b611a97565b34801561085f57600080fd5b506011546001600160a01b03166104b8565b34801561087d57600080fd5b5061044161088c366004614e01565b6009546001600160a01b0391821691161490565b61041f6108ae366004614e73565b611b92565b3480156108bf57600080fd5b506104b86108ce366004614c2e565b611c00565b3480156108df57600080fd5b5061041f6108ee366004614f13565b611c60565b3480156108ff57600080fd5b5061048b611df4565b34801561091457600080fd5b5061053e610923366004614e01565b611e82565b34801561093457600080fd5b5061041f611f08565b34801561094957600080fd5b5061041f610958366004614f85565b611f1c565b34801561096957600080fd5b5061097d610978366004615028565b61202e565b6040516001600160e01b0319909116815260200161044d565b3480156109a257600080fd5b5061041f6109b1366004614ddf565b612244565b3480156109c257600080fd5b5061041f6109d1366004615083565b612337565b3480156109e257600080fd5b506104b87f000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab081565b348015610a1657600080fd5b5061097d610a253660046150f2565b612364565b348015610a3657600080fd5b5061053e61258c565b348015610a4b57600080fd5b50610ab2610a5a366004614c2e565b6013602052600090815260409020600181015460028201546003830154600484015460058501546006860154600790960154949593949293919260ff90911691906001600160401b0380821691600160401b90041688565b60405161044d98979695949392919061517a565b348015610ad257600080fd5b50600b546001600160a01b03166104b8565b348015610af057600080fd5b5061041f610aff366004614c2e565b612604565b348015610b1057600080fd5b5061048b612783565b348015610b2557600080fd5b5061053e610b343660046151e5565b612792565b348015610b4557600080fd5b5061041f610b54366004614ddf565b612848565b348015610b6557600080fd5b5061041f610b74366004614e01565b612931565b348015610b8557600080fd5b5061041f610b94366004615220565b6129fc565b348015610ba557600080fd5b5061053e60125481565b348015610bbb57600080fd5b5061041f610bca36600461525a565b612bfa565b348015610bdb57600080fd5b50600e54600f547f00000000000000000000000000000000000000000000000000000000000000e690030161053e565b348015610c1757600080fd5b5061041f610c26366004614e01565b612c0c565b348015610c3757600080fd5b5061041f610c46366004615288565b612c8a565b348015610c5757600080fd5b5061053e7f00000000000000000000000000000000000000000000000000000000000000e681565b348015610c8b57600080fd5b5061048b610c9a366004614c2e565b612cc3565b348015610cab57600080fd5b5061041f610cba366004615345565b612e92565b348015610ccb57600080fd5b5061041f610cda366004614e01565b612ef3565b348015610ceb57600080fd5b50610441610cfa366004615394565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b61041f610d363660046153c2565b612f45565b348015610d4757600080fd5b5061053e610d56366004614c47565b60009081526013602090815260408083206001600160a01b03949094168352929052205490565b348015610d8957600080fd5b5061041f610d98366004614ddf565b612f5b565b348015610da957600080fd5b5061041f610db8366004614e01565b613044565b61041f610dcb366004615401565b6130ba565b348015610ddc57600080fd5b5061041f610deb366004614ddf565b613106565b348015610dfc57600080fd5b5061041f610e0b366004615473565b6131ef565b610e18613305565b6001600160a01b0316610e336011546001600160a01b031690565b6001600160a01b03161480610e715750610e4b613305565b6001600160a01b0316610e66600b546001600160a01b031690565b6001600160a01b0316145b610e965760405162461bcd60e51b8152600401610e8d9061549f565b60405180910390fd5b6017610ea28282615572565b507f1d7696984a6c8e76fa7d719b93812fa99fec684deb7fef436692056e4c4aab8981604051610ed29190614c1b565b60405180910390a150565b6000610ee882613314565b92915050565b610ef6613339565b610f0082826133b2565b604080516001600160a01b03841681526001600160601b03831660208201527fae1d656a1268648b04ffa79c1416f05879338ae295aae3234d8db217356a1c62910160405180910390a15050565b606060028054610f5d906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610f89906154f0565b8015610fd65780601f10610fab57610100808354040283529160200191610fd6565b820191906000526020600020905b815481529060010190602001808311610fb957829003601f168201915b5050505050905090565b6000610feb826134af565b506000908152600660205260409020546001600160a01b031690565b600061101282611c00565b9050806001600160a01b0316836001600160a01b03160361107f5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610e8d565b806001600160a01b0316611091613305565b6001600160a01b031614806110ad57506110ad81610cfa613305565b61111f5760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610e8d565b611129838361350e565b505050565b611136613305565b6001600160a01b03166111516011546001600160a01b031690565b6001600160a01b0316148061118f5750611169613305565b6001600160a01b0316611184600b546001600160a01b031690565b6001600160a01b0316145b6111ab5760405162461bcd60e51b8152600401610e8d9061549f565b818110156111cc5760405163b7d0949760e01b815260040160405180910390fd5b601254600090815260136020526040902060070154600160401b90046001600160401b03168210156112115760405163b7d0949760e01b815260040160405180910390fd5b60006013600060126000815461122690615647565b918290555081526020810191909152604001600020600581018054919250899160ff19166001838181111561125d5761125d615164565b021790555060018082018890556002820187905560048201869055600682018590556007820180546001600160401b03858116600160401b026001600160801b031990921690871617179055601254907f2f97fd490e935512c57b9c40169523f1fffb4291d075d10c2de74783f22ef95c908a908111156112e0576112e0615164565b60408051918252602082018b90528101899052606081018890526080810187905260a0810186905260c0810185905260e00160405180910390a25050505050505050565b6000818152600460205260408120546001600160a01b031661137a5760405162461bcd60e51b815260206004820152600f60248201526e21554e4b4e4f574e5f544f4b454e2160881b6044820152606401610e8d565b5060009081526008602052604090205490565b60006010546113c2600e54600f547f00000000000000000000000000000000000000000000000000000000000000e690030190565b03905090565b336001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e6990916146114425760405163073e64fd60e21b81523360048201526001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909166024820152604401610e8d565b61144c828261357c565b5050565b61146161145b613305565b8261359f565b61147d5760405162461bcd60e51b8152600401610e8d90615660565b61112983838361361d565b60008281526001602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916114fd5750604080518082019091526000546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101516000906127109061151c906001600160601b0316876156ae565b61152691906156db565b91519350909150505b9250929050565b61153e613305565b6001600160a01b03166115596011546001600160a01b031690565b6001600160a01b031614806115975750611571613305565b6001600160a01b031661158c600b546001600160a01b031690565b6001600160a01b0316145b6115b35760405162461bcd60e51b8152600401610e8d9061549f565b6002600a54036116055760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e8d565b6002600a55806001810161169a576014546001600160a01b031615611695576014546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561166c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169091906156ef565b611697565b475b90505b601954600090612710906116b990600160a01b900461ffff16846156ae565b6116c391906156db565b905060006116d18284615708565b6014549091506001600160a01b03166117ac576018546040516000916001600160a01b03169084908381818185875af1925050503d8060008114611731576040519150601f19603f3d011682016040523d82523d6000602084013e611736565b606091505b505090508061174457600080fd5b6019546040516001600160a01b03909116908390600081818185875af1925050503d8060008114611791576040519150601f19603f3d011682016040523d82523d6000602084013e611796565b606091505b505080915050806117a657600080fd5b506118a1565b60145460185460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810185905291169063a9059cbb906044016020604051808303816000875af1158015611801573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611825919061571b565b5060145460195460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810184905291169063a9059cbb906044016020604051808303816000875af115801561187b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189f919061571b565b505b50506001600a555050565b6118b4613305565b6001600160a01b03166118cf6011546001600160a01b031690565b6001600160a01b0316148061190d57506118e7613305565b6001600160a01b0316611902600b546001600160a01b031690565b6001600160a01b0316145b6119295760405162461bcd60e51b8152600401610e8d9061549f565b600019810361196257600e5461195f907f00000000000000000000000000000000000000000000000000000000000000e6615708565b90505b8061196c600e5490565b6119769190615738565b7f00000000000000000000000000000000000000000000000000000000000000e610156119b657604051636ee3e45960e11b815260040160405180910390fd5b80600e60008282546119c89190615738565b909155506119f890507f000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab082613628565b50565b6000467f00000000000000000000000000000000000000000000000000000000000000018114611a3357611a2e8161365f565b611a55565b7f40deacfbaa8dcc30194d0604af7f4186163cabcefa314ac885f33ea4baf258345b91505090565b61112983838360405180602001604052806000815250612c8a565b611a7f8161370b565b60108054906000611a8f83615647565b919050555050565b611a9f613305565b6001600160a01b0316611aba6011546001600160a01b031690565b6001600160a01b03161480611af85750611ad2613305565b6001600160a01b0316611aed600b546001600160a01b031690565b6001600160a01b0316145b611b145760405162461bcd60e51b8152600401610e8d9061549f565b6000815111611b565760405162461bcd60e51b815260206004820152600e60248201526d77726f6e6720626173652075726960901b6044820152606401610e8d565b600c611b628282615572565b507f6741b2fc379fad678116fe3d4d4b9a1a184ab53ba36b86ad0fa66340b1ab41ad81604051610ed29190614c1b565b611ba8611b9f89876156ae565b8585858561373b565b611bf4611bb3613305565b60008c8c808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508e92508d91508c90508b6137df565b50505050505050505050565b6000818152600460205260408120546001600160a01b031680610ee85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b7f000000000000000000000000000000000000000000000000000000000000078a611cb1600e54600f547f00000000000000000000000000000000000000000000000000000000000000e690030190565b1015611cd0576040516303ba630160e01b815260040160405180910390fd5b611cd8613305565b6001600160a01b0316611cf36011546001600160a01b031690565b6001600160a01b03161480611d315750611d0b613305565b6001600160a01b0316611d26600b546001600160a01b031690565b6001600160a01b0316145b611d4d5760405162461bcd60e51b8152600401610e8d9061549f565b601a546040516305d3b1d360e41b8152600481018590526001600160401b038216602482015261ffff8416604482015263ffffffff8316606482015260016084820152600160401b9091046001600160a01b031690635d3b1d309060a4016020604051808303816000875af1158015611dca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dee91906156ef565b50505050565b60178054611e01906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054611e2d906154f0565b8015611e7a5780601f10611e4f57610100808354040283529160200191611e7a565b820191906000526020600020905b815481529060010190602001808311611e5d57829003601f168201915b505050505081565b60006001600160a01b038216611eec5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610e8d565b506001600160a01b031660009081526005602052604090205490565b611f10613339565b611f1a60006139c5565b565b42821015611f6c5760405162461bcd60e51b815260206004820152601960248201527f215045524d49545f444541444c494e455f4558504952454421000000000000006044820152606401610e8d565b600083815260086020526040812054611f89908690869086612792565b90506000611f978284613a17565b5090506001600160a01b03811615801590611fb75750611fb7818661359f565b80611fd05750611fd0611fc986611c00565b8385613a59565b61201c5760405162461bcd60e51b815260206004820152601a60248201527f21494e56414c49445f5045524d49545f5349474e4154555245210000000000006044820152606401610e8d565b612026868661350e565b505050505050565b6014546000906001600160a01b031633146120825760405162461bcd60e51b81526020600482015260146024820152731bdb9b1e48115490cc4ccd8cc81c185e5b595b9d60621b6044820152606401610e8d565b7f71d859275b482dfe1e2d14bfd2863dbe5cc9914143fea269841eb035fd6afaf533868686866040516120b9959493929190615774565b60405180910390a160006120d060048285876157b3565b6120d9916157dd565b905060006120ea84600481886157b3565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050506001600160e01b0319821663134ce68560e01b0161217357600080600080848060200190518101906121539190615818565b935093509350935061216a8b600086868686613b9b565b5050505061222f565b630918955d60e01b6001600160e01b03198316016121cb576000806000806000858060200190518101906121a79190615857565b945094509450945094506121c18c600087878787876137df565b505050505061222f565b60405162461bcd60e51b815260206004820152603360248201527f6f6e417070726f76616c52656365697665643a2066756e6374696f6e2073656c6044820152721958dd1bdc881b9bdd081cdd5c1c1bdc9d1959606a1b6064820152608401610e8d565b506307b04a2d60e41b9150505b949350505050565b818060125410156122685760405163ed6b05a360e01b815260040160405180910390fd5b612270613305565b6001600160a01b031661228b6011546001600160a01b031690565b6001600160a01b031614806122c957506122a3613305565b6001600160a01b03166122be600b546001600160a01b031690565b6001600160a01b0316145b6122e55760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060048101859055915184815285917f945c1c4e99aa89f648fbfe3df471b916f719e16d960fcec0737d4d56bd69683891015b60405180910390a250505050565b612344611b9f89876156ae565b61235a61234f613305565b60008a8a8a8a613b9b565b5050505050505050565b6014546000906001600160a01b031633146123b85760405162461bcd60e51b81526020600482015260146024820152731bdb9b1e48115490cc4ccd8cc81c185e5b595b9d60621b6044820152606401610e8d565b7fa10ea941849680df7289f12b45394b2f603bb88bfd7346374c8e6dbb8fd27fb83387878787876040516123f196959493929190615917565b60405180910390a1600061240860048285876157b3565b612411916157dd565b905036600061242385600481896157b3565b909250905063134ce68560e01b6001600160e01b031984160161249b576000808080612451858701876153c2565b93509350935093508a818561246691906156ae565b146124835760405162461bcd60e51b8152600401610e8d90615953565b6124928c600186868686613b9b565b50505050612577565b630918955d60e01b6001600160e01b0319841601612513576000808080806124c586880188615995565b945094509450945094508b81856124dc91906156ae565b146124f95760405162461bcd60e51b8152600401610e8d90615953565b6125098d600187878787876137df565b5050505050612577565b60405162461bcd60e51b815260206004820152603360248201527f6f6e5472616e7366657252656365697665643a2066756e6374696f6e2073656c6044820152721958dd1bdc881b9bdd081cdd5c1c1bdc9d1959606a1b6064820152608401610e8d565b50632229f29760e21b98975050505050505050565b60008060015b60125481116125fb5760008181526013602052604090206007810154909250426001600160401b03909116118015906125de57506007820154600160401b90046001600160401b031642105b156125e95792915050565b806125f381615647565b915050612592565b50600091505090565b61260c613305565b6001600160a01b03166126276011546001600160a01b031690565b6001600160a01b03161480612665575061263f613305565b6001600160a01b031661265a600b546001600160a01b031690565b6001600160a01b0316145b6126815760405162461bcd60e51b8152600401610e8d9061549f565b60001981036126b15750600f547f000000000000000000000000000000000000000000000000000000000000078a035b601254600090815260136020526040902060070154600160401b90046001600160401b03164210156126f657604051632e25514d60e11b815260040160405180910390fd5b80612722600f547f000000000000000000000000000000000000000000000000000000000000078a0390565b101561274157604051630a5b751b60e41b815260040160405180910390fd5b80600f60008282546127539190615738565b909155506119f890507f000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab082613d4d565b606060038054610f5d906154f0565b600061283f61279f6119fb565b604080517f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad6020808301919091526001600160a01b038a1682840152606082018990526080820188905260a08083018890528351808403909101815260c08301845280519082012061190160f01b60e084015260e28301949094526101028083019490945282518083039094018452610122909101909152815191012090565b95945050505050565b8180601254101561286c5760405163ed6b05a360e01b815260040160405180910390fd5b612874613305565b6001600160a01b031661288f6011546001600160a01b031690565b6001600160a01b031614806128cd57506128a7613305565b6001600160a01b03166128c2600b546001600160a01b031690565b6001600160a01b0316145b6128e95760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060028101859055915184815285917fc37cc9c3c37fdcacbe05156c2f68f96e3d3ecec5a381a8929651bf7a317f0d1c9101612329565b612939613305565b6001600160a01b03166129546011546001600160a01b031690565b6001600160a01b03161480612992575061296c613305565b6001600160a01b0316612987600b546001600160a01b031690565b6001600160a01b0316145b6129ae5760405162461bcd60e51b8152600401610e8d9061549f565b601480546001600160a01b0319166001600160a01b0383169081179091556040519081527f424cf801e48c82bd3bcec24e3c7b5912fbdd079dad1e9137321af112db07381f90602001610ed2565b82806012541015612a205760405163ed6b05a360e01b815260040160405180910390fd5b612a28613305565b6001600160a01b0316612a436011546001600160a01b031690565b6001600160a01b03161480612a815750612a5b613305565b6001600160a01b0316612a76600b546001600160a01b031690565b6001600160a01b0316145b612a9d5760405162461bcd60e51b8152600401610e8d9061549f565b82821015612abe5760405163b7d0949760e01b815260040160405180910390fd5b600084815260136020526040902060125485108015612b0757508260136000612ae8886001615738565b81526020810191909152604001600020600701546001600160401b0316105b15612b255760405163b7d0949760e01b815260040160405180910390fd5b846001108015612b66575060136000612b3f600188615708565b8152602081019190915260400160002060070154600160401b90046001600160401b031684105b15612b845760405163b7d0949760e01b815260040160405180910390fd5b6007810180546001600160401b03858116600160401b026001600160801b03199092169087161717905560405185907f2ce088ba9de5c469723f27edb3150dd5b001a016d992fed4a7e1d0c1cc39137290612beb9087908790918252602082015260400190565b60405180910390a25050505050565b61144c612c05613305565b8383613d84565b612c14613339565b6001600160a01b038116612c815760405162461bcd60e51b815260206004820152602e60248201527f4e656f77697a4552433732313a206e6577206f70657261746f7220697320746860448201526d65207a65726f206164647265737360901b6064820152608401610e8d565b6119f881613e52565b612c9b612c95613305565b8361359f565b612cb75760405162461bcd60e51b8152600401610e8d90615660565b611dee84848484613ea0565b6060612cce826134af565b60165460ff16612d6a5760178054612ce5906154f0565b80601f0160208091040260200160405190810160405280929190818152602001828054612d11906154f0565b8015612d5e5780601f10612d3357610100808354040283529160200191612d5e565b820191906000526020600020905b815481529060010190602001808311612d4157829003601f168201915b50505050509050919050565b60007f00000000000000000000000000000000000000000000000000000000000000e6831015612d9b575081612e34565b7f00000000000000000000000000000000000000000000000000000000000000e6612de6817f000000000000000000000000000000000000000000000000000000000000078a615708565b601554612e137f00000000000000000000000000000000000000000000000000000000000000e687615708565b612e1d9190615738565b612e2791906159ff565b612e319190615738565b90505b6000600c8054612e43906154f0565b905011612e5f5760405180602001604052806000815250612e8b565b600c612e6a82613ed3565b604051602001612e7b929190615a13565b6040516020818303038152906040525b9392505050565b6040516bffffffffffffffffffffffff19606083901b166020820152600090603401604051602081830303815290604052805190602001209050612ed7848483613fd3565b611dee576040516227b15560e01b815260040160405180910390fd5b612efb613339565b600980546001600160a01b0319166001600160a01b0383169081179091556040517fffd948da7ce0ac541cf3790b301b0df6af19e474ed095744d1460a7ea6b7d15390600090a250565b611dee612f50613305565b600086868686613b9b565b81806012541015612f7f5760405163ed6b05a360e01b815260040160405180910390fd5b612f87613305565b6001600160a01b0316612fa26011546001600160a01b031690565b6001600160a01b03161480612fe05750612fba613305565b6001600160a01b0316612fd5600b546001600160a01b031690565b6001600160a01b0316145b612ffc5760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060068101859055915184815285917f9ff79792a92b66fee090acb66e07837a2edb31ee6b9780fa551fd04b79dffcd29101612329565b61304c613339565b6001600160a01b0381166130b15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e8d565b6119f8816139c5565b6120266130c5613305565b60008888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250899150889050876137df565b8180601254101561312a5760405163ed6b05a360e01b815260040160405180910390fd5b613132613305565b6001600160a01b031661314d6011546001600160a01b031690565b6001600160a01b0316148061318b5750613165613305565b6001600160a01b0316613180600b546001600160a01b031690565b6001600160a01b0316145b6131a75760405162461bcd60e51b8152600401610e8d9061549f565b60008381526013602090815260409182902060018101859055915184815285917f258fa6ef7a3f3b3f76e4871e78d8e046e00bcf3f3e2662a58b3da774a2a74f399101612329565b818060125410156132135760405163ed6b05a360e01b815260040160405180910390fd5b61321b613305565b6001600160a01b03166132366011546001600160a01b031690565b6001600160a01b03161480613274575061324e613305565b6001600160a01b0316613269600b546001600160a01b031690565b6001600160a01b0316145b6132905760405162461bcd60e51b8152600401610e8d9061549f565b600083815260136020526040902060058101805484919060ff1916600183818111156132be576132be615164565b0217905550837f210cbb60935822c957f36bfad9f082e34516b470d608565d6e21abfd2d771beb8460018111156132f7576132f7615164565b604051908152602001612329565b600061330f613fe9565b905090565b60006001600160e01b03198216635604e22560e01b1480610ee85750610ee882614010565b613341613305565b6001600160a01b031661335c600b546001600160a01b031690565b6001600160a01b031614611f1a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e8d565b6127106001600160601b03821611156134205760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610e8d565b6001600160a01b0382166134765760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610e8d565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600055565b6000818152600460205260409020546001600160a01b03166119f85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b600081815260066020526040902080546001600160a01b0319166001600160a01b038416908117909155819061354382611c00565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b61144c8160008151811061359257613592615a9a565b602002602001015161401b565b6000806135ab83611c00565b9050806001600160a01b0316846001600160a01b031614806135f257506001600160a01b0380821660009081526007602090815260408083209388168352929052205460ff165b8061223c5750836001600160a01b031661360b84610fe0565b6001600160a01b031614949350505050565b6111298383836140cf565b600081600e546136389190615708565b9050805b6136468383615738565b811015611dee5761365784826140e3565b60010161363c565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61368a610f4e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b61371661145b613305565b6137325760405162461bcd60e51b8152600401610e8d90615660565b6119f8816140fd565b6014546001600160a01b031663d505accf613754613305565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018890526064810187905260ff8616608482015260a4810185905260c4810184905260e401600060405180830381600087803b1580156137c057600080fd5b505af11580156137d4573d6000803e3d6000fd5b505050505050505050565b60008381526013602052604090206012548491908211156138135760405163363a51ef60e01b815260040160405180910390fd5b60078101546001600160401b0316421015613841576040516323a71b8760e21b815260040160405180910390fd5b600781015442600160401b9091046001600160401b03161161387657604051636b5fd31b60e01b815260040160405180910390fd5b600085815260136020526040812060050154869160ff909116908160018111156138a2576138a2615164565b146138c057604051630a7bec6d60e21b815260040160405180910390fd5b60008781526013602052604090206014546001600160a01b038881169116146139225760405162461bcd60e51b81526020600482015260146024820152731c185e5b595b9d081a5cc8191a5999995c995b9d60621b6044820152606401610e8d565b806004015486146139705760405162461bcd60e51b81526020600482015260186024820152771c9bdd5b99081c1c9a58d9481a5cc8191a5999995c995b9d60421b6044820152606401610e8d565b60008881526013602052604090206006015461398e908b908e612e92565b8a6139ac576139ac8c8a83600401546139a791906156ae565b614106565b6139b7888d8b614242565b505050505050505050505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000808251604103613a4d5760208301516040840151606085015160001a613a41878285856143a3565b9450945050505061152f565b5060009050600261152f565b6000806000613a688585613a17565b90925090506000816004811115613a8157613a81615164565b148015613a9f5750856001600160a01b0316826001600160a01b0316145b15613aaf57600192505050612e8b565b600080876001600160a01b0316631626ba7e60e01b8888604051602401613ad7929190615ab0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613b159190615ac9565b600060405180830381855afa9150503d8060008114613b50576040519150601f19603f3d011682016040523d82523d6000602084013e613b55565b606091505b5091509150818015613b68575080516020145b8015613b8f57508051630b135d3f60e11b90613b8d90830160209081019084016156ef565b145b98975050505050505050565b6000838152601360205260409020601254849190821115613bcf5760405163363a51ef60e01b815260040160405180910390fd5b60078101546001600160401b0316421015613bfd576040516323a71b8760e21b815260040160405180910390fd5b600781015442600160401b9091046001600160401b031611613c3257604051636b5fd31b60e01b815260040160405180910390fd5b84600160008281526013602052604090206005015460ff166001811115613c5b57613c5b615164565b14613c7957604051637002ac7160e11b815260040160405180910390fd5b60008681526013602052604090206014546001600160a01b03878116911614613cdb5760405162461bcd60e51b81526020600482015260146024820152731c185e5b595b9d081a5cc8191a5999995c995b9d60621b6044820152606401610e8d565b80600401548514613d295760405162461bcd60e51b81526020600482015260186024820152771c9bdd5b99081c1c9a58d9481a5cc8191a5999995c995b9d60421b6044820152606401610e8d565b88613d4257613d428a8983600401546139a791906156ae565b611bf4878b8a614242565b600081600f54613d5d9190615708565b9050805b613d6b8383615738565b811015611dee57613d7c84826140e3565b600101613d61565b816001600160a01b0316836001600160a01b031603613de55760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610e8d565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b601180546001600160a01b0319166001600160a01b0383169081179091556040519081527fda12ee837e6978172aaf54b16145ffe08414fd8710092ef033c71b8eb6ec189a90602001610ed2565b613eab84848461361d565b613eb784848484614490565b611dee5760405162461bcd60e51b8152600401610e8d90615ae5565b606081600003613efa5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613f245780613f0e81615647565b9150613f1d9050600a836156db565b9150613efe565b6000816001600160401b03811115613f3e57613f3e614a59565b6040519080825280601f01601f191660200182016040528015613f68576020820181803683370190505b5090505b841561223c57613f7d600183615708565b9150613f8a600a866159ff565b613f95906030615738565b60f81b818381518110613faa57613faa615a9a565b60200101906001600160f81b031916908160001a905350613fcc600a866156db565b9450613f6c565b600082613fe08584614595565b14949350505050565b6009546000906001600160a01b0316330361400b575060131936013560601c90565b503390565b6000610ee8826145d8565b60165460ff161561403f5760405163a89ac15160e01b815260040160405180910390fd5b6140897f00000000000000000000000000000000000000000000000000000000000000e67f000000000000000000000000000000000000000000000000000000000000078a615708565b61409390826159ff565b6015556016805460ff191660011790556040517fe2a7169cedebe39671840370ae19ca4fc41be6191d4c77f174f189a4d8cd08c890600090a150565b6140d881614618565b611129838383614632565b61144c8282604051806020016040528060008152506147ce565b6119f881614801565b6014546001600160a01b031615614221576014546040516370a0823160e01b81526001600160a01b038481166004830152839216906370a0823190602401602060405180830381865afa158015614161573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418591906156ef565b10156141a4576040516302b1b38b60e61b815260040160405180910390fd5b6014546040516323b872dd60e01b81526001600160a01b03848116600483015230602483015260448201849052909116906323b872dd906064016020604051808303816000875af11580156141fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611129919061571b565b8034101561144c57604051634a531cfd60e01b815260040160405180910390fd5b60008381526013602090815260408083206001600160a01b03861684529182905290912054614272908390615738565b816001015410156142a85760405163c86a5f3560e01b8152600481018590526001600160a01b0384166024820152604401610e8d565b60125484141580156142cc57508181600301546142c59190615738565b8160020154105b156142ec57604051626dc22f60e91b815260048101859052602401610e8d565b81614318600f547f000000000000000000000000000000000000000000000000000000000000078a0390565b101561433757604051630a5b751b60e41b815260040160405180910390fd5b6001600160a01b0383166000908152602082905260408120805484929061435f908490615738565b925050819055508181600301600082825461437a9190615738565b9250508190555081600f60008282546143939190615738565b90915550611dee90508383613d4d565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156143da5750600090506003614487565b8460ff16601b141580156143f257508460ff16601c14155b156144035750600090506004614487565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614457573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661448057600060019250925050614487565b9150600090505b94509492505050565b60006001600160a01b0384163b1561458d57836001600160a01b031663150b7a026144b9613305565b8786866040518563ffffffff1660e01b81526004016144db9493929190615b37565b6020604051808303816000875af1925050508015614516575060408051601f3d908101601f1916820190925261451391810190615b74565b60015b614573573d808015614544576040519150601f19603f3d011682016040523d82523d6000602084013e614549565b606091505b50805160000361456b5760405162461bcd60e51b8152600401610e8d90615ae5565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061223c565b50600161223c565b600081815b84518110156145d0576145c6828683815181106145b9576145b9615a9a565b602002602001015161481b565b915060010161459a565b509392505050565b60006001600160e01b031982166380ac58cd60e01b148061460957506001600160e01b03198216635b5e139f60e01b145b80610ee85750610ee882614847565b6000818152600860205260408120805491611a8f83615647565b826001600160a01b031661464582611c00565b6001600160a01b0316146146a95760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610e8d565b6001600160a01b03821661470b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610e8d565b61471660008261350e565b6001600160a01b038316600090815260056020526040812080546001929061473f908490615708565b90915550506001600160a01b038216600090815260056020526040812080546001929061476d908490615738565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6147d8838361487c565b6147e56000848484614490565b6111295760405162461bcd60e51b8152600401610e8d90615ae5565b61480a816149be565b600090815260016020526040812055565b6000818310614837576000828152602084905260409020612e8b565b5060009182526020526040902090565b60006001600160e01b0319821663152a902d60e11b1480610ee857506301ffc9a760e01b6001600160e01b0319831614610ee8565b6001600160a01b0382166148d25760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610e8d565b6000818152600460205260409020546001600160a01b0316156149375760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6001600160a01b0382166000908152600560205260408120805460019290614960908490615738565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006149c982611c00565b90506149d660008361350e565b6001600160a01b03811660009081526005602052604081208054600192906149ff908490615708565b909155505060008281526004602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614a9757614a97614a59565b604052919050565b60006001600160401b03831115614ab857614ab8614a59565b614acb601f8401601f1916602001614a6f565b9050828152838383011115614adf57600080fd5b828260208301376000602084830101529392505050565b600060208284031215614b0857600080fd5b81356001600160401b03811115614b1e57600080fd5b8201601f81018413614b2f57600080fd5b61223c84823560208401614a9f565b6001600160e01b0319811681146119f857600080fd5b600060208284031215614b6657600080fd5b8135612e8b81614b3e565b6001600160a01b03811681146119f857600080fd5b60008060408385031215614b9957600080fd5b8235614ba481614b71565b915060208301356001600160601b0381168114614bc057600080fd5b809150509250929050565b60005b83811015614be6578181015183820152602001614bce565b50506000910152565b60008151808452614c07816020860160208601614bcb565b601f01601f19169290920160200192915050565b602081526000612e8b6020830184614bef565b600060208284031215614c4057600080fd5b5035919050565b60008060408385031215614c5a57600080fd5b8235614c6581614b71565b946020939093013593505050565b803560028110614c8257600080fd5b919050565b600080600080600080600060e0888a031215614ca257600080fd5b614cab88614c73565b9960208901359950604089013598606081013598506080810135975060a0810135965060c00135945092505050565b60006001600160401b03821115614cf357614cf3614a59565b5060051b60200190565b60008060408385031215614d1057600080fd5b823591506020808401356001600160401b03811115614d2e57600080fd5b8401601f81018613614d3f57600080fd5b8035614d52614d4d82614cda565b614a6f565b81815260059190911b82018301908381019088831115614d7157600080fd5b928401925b82841015614d8f57833582529284019290840190614d76565b80955050505050509250929050565b600080600060608486031215614db357600080fd5b8335614dbe81614b71565b92506020840135614dce81614b71565b929592945050506040919091013590565b60008060408385031215614df257600080fd5b50508035926020909101359150565b600060208284031215614e1357600080fd5b8135612e8b81614b71565b60008083601f840112614e3057600080fd5b5081356001600160401b03811115614e4757600080fd5b6020830191508360208260051b850101111561152f57600080fd5b803560ff81168114614c8257600080fd5b6000806000806000806000806000806101208b8d031215614e9357600080fd5b8a356001600160401b03811115614ea957600080fd5b614eb58d828e01614e1e565b909b5099505060208b0135975060408b0135965060608b0135614ed781614b71565b955060808b0135945060a08b01359350614ef360c08c01614e62565b925060e08b013591506101008b013590509295989b9194979a5092959850565b600080600060608486031215614f2857600080fd5b83359250602084013561ffff81168114614f4157600080fd5b9150604084013563ffffffff81168114614f5a57600080fd5b809150509250925092565b600082601f830112614f7657600080fd5b612e8b83833560208501614a9f565b60008060008060808587031215614f9b57600080fd5b8435614fa681614b71565b9350602085013592506040850135915060608501356001600160401b03811115614fcf57600080fd5b614fdb87828801614f65565b91505092959194509250565b60008083601f840112614ff957600080fd5b5081356001600160401b0381111561501057600080fd5b60208301915083602082850101111561152f57600080fd5b6000806000806060858703121561503e57600080fd5b843561504981614b71565b93506020850135925060408501356001600160401b0381111561506b57600080fd5b61507787828801614fe7565b95989497509550505050565b600080600080600080600080610100898b0312156150a057600080fd5b883597506020890135965060408901356150b981614b71565b955060608901359450608089013593506150d560a08a01614e62565b925060c0890135915060e089013590509295985092959890939650565b60008060008060006080868803121561510a57600080fd5b853561511581614b71565b9450602086013561512581614b71565b93506040860135925060608601356001600160401b0381111561514757600080fd5b61515388828901614fe7565b969995985093965092949392505050565b634e487b7160e01b600052602160045260246000fd5b600061010082019050898252886020830152876040830152866060830152600286106151b657634e487b7160e01b600052602160045260246000fd5b608082019590955260a08101939093526001600160401b0391821660c08401521660e090910152949350505050565b600080600080608085870312156151fb57600080fd5b843561520681614b71565b966020860135965060408601359560600135945092505050565b60008060006060848603121561523557600080fd5b505081359360208301359350604090920135919050565b80151581146119f857600080fd5b6000806040838503121561526d57600080fd5b823561527881614b71565b91506020830135614bc08161524c565b6000806000806080858703121561529e57600080fd5b84356152a981614b71565b935060208501356152b981614b71565b92506040850135915060608501356001600160401b03811115614fcf57600080fd5b600082601f8301126152ec57600080fd5b813560206152fc614d4d83614cda565b8083825260208201915060208460051b87010193508684111561531e57600080fd5b602086015b8481101561533a5780358352918301918301615323565b509695505050505050565b60008060006060848603121561535a57600080fd5b83356001600160401b0381111561537057600080fd5b61537c868287016152db565b935050602084013591506040840135614f5a81614b71565b600080604083850312156153a757600080fd5b82356153b281614b71565b91506020830135614bc081614b71565b600080600080608085870312156153d857600080fd5b843593506020850135925060408501356153f181614b71565b9396929550929360600135925050565b60008060008060008060a0878903121561541a57600080fd5b86356001600160401b0381111561543057600080fd5b61543c89828a01614e1e565b9097509550506020870135935060408701359250606087013561545e81614b71565b80925050608087013590509295509295509295565b6000806040838503121561548657600080fd5b8235915061549660208401614c73565b90509250929050565b60208082526031908201527f4e656f77697a4552433732313a2063616c6c6572206973206e6f74207468652060408201527037b832b930ba37b91037b91037bbb732b960791b606082015260800190565b600181811c9082168061550457607f821691505b60208210810361552457634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611129576000816000526020600020601f850160051c810160208610156155535750805b601f850160051c820191505b818110156120265782815560010161555f565b81516001600160401b0381111561558b5761558b614a59565b61559f8161559984546154f0565b8461552a565b602080601f8311600181146155d457600084156155bc5750858301515b600019600386901b1c1916600185901b178555612026565b600085815260208120601f198616915b82811015615603578886015182559484019460019091019084016155e4565b50858210156156215787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b60006001820161565957615659615631565b5060010190565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b8082028115828204841417610ee857610ee8615631565b634e487b7160e01b600052601260045260246000fd5b6000826156ea576156ea6156c5565b500490565b60006020828403121561570157600080fd5b5051919050565b81810381811115610ee857610ee8615631565b60006020828403121561572d57600080fd5b8151612e8b8161524c565b80820180821115610ee857610ee8615631565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b03868116825285166020820152604081018490526080606082018190526000906157a8908301848661574b565b979650505050505050565b600080858511156157c357600080fd5b838611156157d057600080fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156158055780818660040360031b1b83161692505b505092915050565b8051614c8281614b71565b6000806000806080858703121561582e57600080fd5b8451935060208501519250604085015161584781614b71565b6060959095015193969295505050565b600080600080600060a0868803121561586f57600080fd5b85516001600160401b0381111561588557600080fd5b8601601f8101881361589657600080fd5b805160206158a6614d4d83614cda565b82815260059290921b8301810191818101908b8411156158c557600080fd5b938201935b838510156158e3578451825293820193908201906158ca565b8099505050808901519650505050604086015192506159046060870161580d565b9150608086015190509295509295909350565b6001600160a01b0387811682528681166020830152851660408201526060810184905260a060808201819052600090613b8f908301848661574b565b60208082526022908201527f6f6e5472616e7366657252656365697665643a20696e76616c696420616d6f756040820152611b9d60f21b606082015260800190565b600080600080600060a086880312156159ad57600080fd5b85356001600160401b038111156159c357600080fd5b6159cf888289016152db565b955050602086013593506040860135925060608601356159ee81614b71565b949793965091946080013592915050565b600082615a0e57615a0e6156c5565b500690565b6000808454615a21816154f0565b60018281168015615a395760018114615a4e57615a7d565b60ff1984168752821515830287019450615a7d565b8860005260208060002060005b85811015615a745781548a820152908401908201615a5b565b50505082870194505b505050508351615a91818360208801614bcb565b01949350505050565b634e487b7160e01b600052603260045260246000fd5b82815260406020820152600061223c6040830184614bef565b60008251615adb818460208701614bcb565b9190910192915050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615b6a90830184614bef565b9695505050505050565b600060208284031215615b8657600080fd5b8151612e8b81614b3e56fea26469706673582212202fb497ab354989fe8376313f570296e60952c6e1a03c9c7f953a822b9686986464736f6c63430008170033

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

00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000078a00000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000380000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909000000000000000000000000d255647b9f573916e676db77cd34c9e8bd00528a000000000000000000000000cb9440b0d963c54a6d68aa847517f2ed5311d4ba000000000000000000000000000000000000000000000000000000000000232800000000000000000000000000000000000000000000000000000000000000174561726c792052657469726564204361747320436c7562000000000000000000000000000000000000000000000000000000000000000000000000000000000445524343000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d6648797635587a50723878336355474679623575316e694d666e315268337a336a74715033693842656a6b460000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): Early Retired Cats Club
Arg [1] : _symbol (string): ERCC
Arg [2] : _maxTotalSupply (uint256): 1930
Arg [3] : _teamSupply (uint256): 230
Arg [4] : _team (address): 0xe00C795377C1b8E7F726e9C4AadCe8fEC1beEAB0
Arg [5] : _payment (address): 0x0000000000000000000000000000000000000000
Arg [6] : _unrevealedURI (string): ipfs://QmfHyv5XzPr8x3cUGFyb5u1niMfn1Rh3z3jtqP3i8BejkF
Arg [7] : _trustedForwarder (address): 0x0000000000000000000000000000000000000000
Arg [8] : _subscriptionId (uint64): 896
Arg [9] : _vrfCoordinator (address): 0x271682DEB8C4E0901D1a1550aD2e64D568E69909
Arg [10] : _salesInfo (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
20 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000001a0
Arg [1] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [2] : 000000000000000000000000000000000000000000000000000000000000078a
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000e6
Arg [4] : 000000000000000000000000e00c795377c1b8e7f726e9c4aadce8fec1beeab0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000220
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000380
Arg [9] : 000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909
Arg [10] : 000000000000000000000000d255647b9f573916e676db77cd34c9e8bd00528a
Arg [11] : 000000000000000000000000cb9440b0d963c54a6d68aa847517f2ed5311d4ba
Arg [12] : 0000000000000000000000000000000000000000000000000000000000002328
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [14] : 4561726c792052657469726564204361747320436c7562000000000000000000
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [16] : 4552434300000000000000000000000000000000000000000000000000000000
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000035
Arg [18] : 697066733a2f2f516d6648797635587a50723878336355474679623575316e69
Arg [19] : 4d666e315268337a336a74715033693842656a6b460000000000000000000000


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.