ETH Price: $3,668.87 (+0.79%)

Token

ERC-20: Thunderbirds International Rescue Club (FAB)
 

Overview

Max Total Supply

5,424 FAB

Holders

3,761

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 FAB
0xcab1f1cb0fbebcd58c15dc0c0d077251ba0f08e3
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Thunderbirds

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Multiple files format)

File 9 of 9: Thunderbirds.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.16;

import "./ERC721.sol";
import "./Ownership.sol";

interface IMintPass {
    function getRedeemedTimes(uint256 tokenId) external view returns(uint8);
    function ownerOf(uint256 _tokenId) external view returns (address);
    function balanceOf(address _owner) external view returns (uint256);
    function exists(uint256 _tokenId) external view returns (bool);
    function tokenOfOwnerByIndex(address _owner, uint256 _index)
        external
        view
        returns (uint256 _tokenId);
    function updateRedeemedTimes(uint256 tokenId, uint8 _redeemedTimes) external;
}

contract Thunderbirds is ERC721, Ownership {

    uint256 public maxSupply; // max supply of nft
    uint256 public preSaleStarts;
    uint256 public preSaleEnds;
    uint256 public saleEnds;
    IMintPass private mintPass;
    bool public isPaused = false; // pause the contractn when something goes "really" wrong
    uint256 public price;
    address payable public coldWallet;
    uint256 public mintedForTeam;
    bool public isRevealed;

    uint256 private constant reservedForTeam = 30;
    uint8 private constant MAX_REDEEME_COUNT = 3;

    // nonce to prevent replay attack on admin signature
    mapping(address => mapping(uint => bool)) public isSignerNonceUsed;

    struct Signature {
        bytes32 r;
        bytes32 s;
        uint8 v;
    }


    event Paused(bool _isPaused);
    event PriceUpdate(uint256 oldPrice, uint256 newPrice);


    modifier notPaused() {
        require(!isPaused, "Contract paused");
        _;
    }
    

    modifier canMint(uint8 quantity) {
        require(block.timestamp >= preSaleStarts , "Sale not live yet");
        require(block.timestamp < saleEnds, "Sale closed");
        require(totalSupply() + quantity <= maxSupply - reservedForTeam, "Sold out");
        require(msg.value == price*quantity, "Incorrect fee");
        _;
    }


    constructor(
        address _mintPassContract,
        uint256 _preSaleStarts,
        uint256 _preSaleEnds,
        address payable _coldWallet,
        uint256 _price,
        string memory _baseurl
    )
        ERC721("Thunderbirds International Rescue Club", "FAB", _baseurl, ".json")
    {
        mintPass = IMintPass(_mintPassContract);
        maxSupply = 5432;
        price = _price;
        coldWallet = _coldWallet;
        preSaleStarts = _preSaleStarts;
        preSaleEnds = _preSaleEnds;
        saleEnds = preSaleEnds + 1 weeks;
        isRevealed = false;
    }

    function mint(address user, uint8 quantity) public payable canMint(quantity) notPaused {
        require(block.timestamp >= preSaleEnds, "Only mintpass holders allowed in presale");
        coldWallet.transfer(msg.value);
        _batchMint(user, quantity);
    }

    function mintWithPass(address user, uint8 quantity, uint256 mintPassId) public payable canMint(quantity) {
        require(block.timestamp < preSaleEnds, "Pre-sale ended");
        require(mintPass.exists(mintPassId), "Invalid mint pass");
        require(mintPass.ownerOf(mintPassId) == msg.sender, "Sender does not own given mint pass");
        coldWallet.transfer(msg.value);
        uint8 redeemedTimes = mintPass.getRedeemedTimes(mintPassId);
        require(redeemedTimes+quantity <= MAX_REDEEME_COUNT, "Mint pass redeemed");
        mintPass.updateRedeemedTimes(mintPassId, redeemedTimes+quantity);
        _batchMint(user, quantity);
    }

    function mintReservedTokens(address[] memory users) public onlyDeputyOrOwner {
        require(mintedForTeam + users.length <= reservedForTeam, "Max reserved tokens minted");
        unchecked {
            mintedForTeam += users.length;
        }
        for(uint8 i=0; i<users.length; i++) {
            super.mint(users[i], totalSupply()+1);
        }
    }


    function updatePrice(uint256 _price) public onlyOwner {
        emit PriceUpdate(price, _price);
        price = _price;
    }


    function _batchMint(address user, uint8 quantity) internal  {
        for(uint8 i=0; i<quantity; i++) {
            super.mint(user, totalSupply() + 1);
        }
    }

    
    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public override notPaused {
        super._transferFrom(_from, _to, _tokenId);
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public override notPaused {
        super._safeTransferFrom(_from, _to, _tokenId, "0x");
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) public override notPaused {
        super._safeTransferFrom(_from, _to, _tokenId, _data);
    }

    function burn(uint256 _tokenId) public override notPaused {
        super.burn(_tokenId);
    }
    
    function preAuthTransfer(
        address _from, address _to, uint256 _tokenId, uint256 signerNonce, Signature memory signature
    ) public notPaused {
        require(
            !isSignerNonceUsed[_from][signerNonce],
            "Duplicate nonce in signature"
        );

        bytes32 hash = keccak256(
            abi.encodePacked(
                bytes4(keccak256("transfer")),
                address(this),
                signerNonce,
                getChainID(),
                _from,
                _to,
                _tokenId
            )
        );
        address signer = getSigner(hash, signature);
        require(signer == _from, "Owner and signer don't match");
        isSignerNonceUsed[signer][signerNonce] = true;
        super._transferOnBehalf(signer, _to, _tokenId);
    }

    function updateBaseTokenUri(string memory _baseTokenUri) public onlyOwner {
        super._updateBaseTokenUri(_baseTokenUri);
    }

    function pauseContract(bool _isPaused) public onlyOwner{
        isPaused = _isPaused;
        emit Paused(_isPaused);
    }

    function reveal() public onlyOwner {
        isRevealed = true;
    }

    function tokenURI(uint256 _tokenId)
        public
        view
        override
        returns (string memory)
    {
        require(exists(_tokenId), "Asset does not exist");
        if(!isRevealed) return baseTokenURI;
        return super._tokenURI(_tokenId);
    }

    function getSigner(bytes32 message, Signature memory sig)
        public
        pure
        returns (address)
    {
        bytes memory prefix = "\x19Ethereum Signed Message:\n32";
        bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, message));
        address signer = ecrecover(prefixedHash, sig.v, sig.r, sig.s);
        return signer;
    }

    function getChainID() internal view returns (uint256) {
        uint256 id;
        assembly {
            id := chainid()
        }
        return id;
    }

}

File 1 of 9: Addresses.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.16;

/**
 * Utility library of inline functions on addresses
 */
library Address {
    /**
     * Returns whether the target address is a contract
     * @dev This function will return false if invoked during the constructor of a contract,
     * as the code is not actually created until after the constructor finishes.
     * @param account address to check
     * @return whether the target address is a contract
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            codehash := extcodehash(account)
        }
        return (codehash != accountHash && codehash != 0x0);
    }
}

File 2 of 9: BaseERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.16;

import "./Addresses.sol";
import "./Strings.sol";
import "./ERC721Receiver.sol";
import "./IERC721.sol";

abstract contract ERC721BasicToken is IERC721 {
    using Address for address;
    using Strings for uint256;

    bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd;
    bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79;
    bytes4 private constant ERC721_RECEIVED = 0xf0b9e5ba;
    bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63;
    bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f;
    bytes4 private constant InterfaceId_ERC165 = 0x01ffc9a7;

    string internal name_;
    string internal symbol_;
    string public baseTokenURI;

    // Array with all token ids, used for enumeration
    uint256[] internal allTokens;

    // Mapping of interface id to whether or not it's supported
    mapping(bytes4 => bool) internal supportedInterfaces;

    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) internal ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) internal ownedTokensIndex;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) internal allTokensIndex;

    // Mapping from token ID to owner
    mapping(uint256 => address) internal tokenOwner;

    // Mapping from token ID to approved address
    mapping(uint256 => address) internal tokenApprovals;

    // Mapping from owner to number of owned token
    mapping(address => uint256) internal ownedTokensCount;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) internal operatorApprovals;

    /**
     * @dev Guarantees msg.sender is owner of the given token
     * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender
     */
    modifier onlyOwnerOf(uint256 _tokenId) {
        require(ownerOf(_tokenId) == msg.sender, "Only asset owner is allowed");
        _;
    }

    /**
     * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator
     * @param _tokenId uint256 ID of the token to validate
     */
    modifier canTransfer(uint256 _tokenId) {
        require(isApprovedOrOwner(msg.sender, _tokenId), "Can not transfer");
        _;
    }

    constructor(
        string memory _name,
        string memory _symbol,
        string memory _baseTokenUri
    ) {
        name_ = _name;
        symbol_ = _symbol;
        baseTokenURI = _baseTokenUri;

        // register the supported interfaces to confirm to ERC721 via ERC165
        _registerInterface(InterfaceId_ERC721Enumerable);
        _registerInterface(InterfaceId_ERC721Metadata);
        _registerInterface(InterfaceId_ERC721);
        _registerInterface(InterfaceId_ERC721Exists);
        _registerInterface(InterfaceId_ERC165);
    }

    /**
     * @dev Gets the token name
     * @return string representing the token name
     */
    function name() external view returns (string memory) {
        return name_;
    }

    /**
     * @dev Gets the token symbol
     * @return string representing the token symbol
     */
    function symbol() external view returns (string memory) {
        return symbol_;
    }

    /**
     * @dev Returns an URI for a given token ID
     * Throws if the token ID does not exist. May return an empty string.
     * @param _tokenId uint256 ID of the token to query
     */
    function tokenURI(uint256 _tokenId)
        public
        view
        virtual
        returns (string memory)
    {
        require(exists(_tokenId), "Asset does not exist");
        return string(abi.encodePacked(baseTokenURI, _tokenId.toString()));
    }

    /**
     * @dev Gets the balance of the specified address
     * @param _owner address to query the balance of
     * @return uint256 representing the amount owned by the passed address
     */
    function balanceOf(address _owner) public view returns (uint256) {
        require(_owner != address(0), "Zero address not allowed");
        return ownedTokensCount[_owner];
    }

    /**
     * @dev Gets the owner of the specified token ID
     * @param _tokenId uint256 ID of the token to query the owner of
     * @return owner address currently marked as the owner of the given token ID
     */
    function ownerOf(uint256 _tokenId) public view returns (address) {
        address owner = tokenOwner[_tokenId];
        require(owner != address(0), "Token does not exists");
        return owner;
    }

    /**
     * @dev Returns whether the specified token exists
     * @param _tokenId uint256 ID of the token to query the existence of
     * @return whether the token exists
     */
    function exists(uint256 _tokenId) public view returns (bool) {
        address owner = tokenOwner[_tokenId];
        return owner != address(0);
    }

    /**
     * @dev Approves another address to transfer the given token ID
     * The zero address indicates there is no approved address.
     * There can only be one approved address per token at a given time.
     * Can only be called by the token owner or an approved operator.
     * @param _to address to be approved for the given token ID
     * @param _tokenId uint256 ID of the token to be approved
     */
    function _approve(address _to, uint256 _tokenId) internal {
        address owner = ownerOf(_tokenId);
        require(_to != owner, "Can not approve to self");
        require(
            msg.sender == owner || isApprovedForAll(owner, msg.sender),
            "Not allowed to update approvals"
        );

        tokenApprovals[_tokenId] = _to;
        emit Approval(owner, _to, _tokenId);
    }

    /**
     * @dev Gets the approved address for a token ID, or zero if no address set
     * @param _tokenId uint256 ID of the token to query the approval of
     * @return address currently approved for the given token ID
     */
    function getApproved(uint256 _tokenId) public view returns (address) {
        return tokenApprovals[_tokenId];
    }

    /**
     * @dev Sets or unsets the approval of a given operator
     * An operator is allowed to transfer all tokens of the sender on their behalf
     * @param _to operator address to set the approval
     * @param _approved representing the status of the approval to be set
     */
    function _setApprovalForAll(address _to, bool _approved) internal {
        require(_to != msg.sender, "Can not approve to self");
        operatorApprovals[msg.sender][_to] = _approved;
        emit ApprovalForAll(msg.sender, _to, _approved);
    }

    /**
     * @dev Tells whether an operator is approved by a given owner
     * @param _owner owner address which you want to query the approval of
     * @param _operator operator address which you want to query the approval of
     * @return bool whether the given operator is approved by the given owner
     */
    function isApprovedForAll(address _owner, address _operator)
        public
        view
        returns (bool)
    {
        return operatorApprovals[_owner][_operator];
    }

    /**
     * @dev Transfers the ownership of a given token ID to another address
     * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
     * Requires the msg sender to be the owner, approved, or operator
     * @param _from current owner of the token
     * @param _to address to receive the ownership of the given token ID
     * @param _tokenId uint256 ID of the token to be transferred
     */
    function _transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) internal canTransfer(_tokenId) {
        _transfer(_from, _to, _tokenId);
    }

    // This function assumes we have verified that _from is allowed to make transaction
    function _transferOnBehalf(
        address _from,
        address _to,
        uint256 _tokenId
    ) internal {
        require(isApprovedOrOwner(_from, _tokenId), "Can not transfer");
        _transfer(_from, _to, _tokenId);
    }

    function _transfer(
        address _from,
        address _to,
        uint256 _tokenId
    ) private {
        require(_to != address(0), "Zero address not allowed");
        clearApproval(_from, _tokenId);
        removeTokenFrom(_from, _tokenId);
        addTokenTo(_to, _tokenId);

        emit Transfer(_from, _to, _tokenId);
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     *
     * Requires the msg sender to be the owner, approved, or operator
     * @param _from current owner of the token
     * @param _to address to receive the ownership of the given token ID
     * @param _tokenId uint256 ID of the token to be transferred
     */
    function _safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) internal {
        // solium-disable-next-line arg-overflow
        _safeTransferFrom(_from, _to, _tokenId, "");
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg sender to be the owner, approved, or operator
     * @param _from current owner of the token
     * @param _to address to receive the ownership of the given token ID
     * @param _tokenId uint256 ID of the token to be transferred
     * @param _data bytes data to send along with a safe transfer check
     */
    function _safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) internal {
        _transferFrom(_from, _to, _tokenId);
        // solium-disable-next-line arg-overflow
        require(
            checkAndCallSafeTransfer(_from, _to, _tokenId, _data),
            "Safe Transfer failed"
        );
    }

    /**
     * @dev Returns whether the given spender can transfer a given token ID
     * @param _spender address of the spender to query
     * @param _tokenId uint256 ID of the token to be transferred
     * @return bool whether the msg.sender is approved for the given token ID,
     *  is an operator of the owner, or is the owner of the token
     */
    function isApprovedOrOwner(address _spender, uint256 _tokenId)
        internal
        view
        returns (bool)
    {
        address owner = ownerOf(_tokenId);
        // Disable solium check because of
        // https://github.com/duaraghav8/Solium/issues/175
        // solium-disable-next-line operator-whitespace
        return (_spender == owner ||
            getApproved(_tokenId) == _spender ||
            isApprovedForAll(owner, _spender));
    }

    /**
     * @dev Internal function to mint a new token
     * Reverts if the given token ID already exists
     * @param _to The address that will own the minted token
     * @param _tokenId uint256 ID of the token to be minted by the msg.sender
     */
    function _mint(address _to, uint256 _tokenId) internal {
        require(_to != address(0), "Zero address not allowed");
        require(!exists(_tokenId), "Asset already exists");
        addTokenTo(_to, _tokenId);
        allTokensIndex[_tokenId] = allTokens.length;
        allTokens.push(_tokenId);

        emit Transfer(address(0), _to, _tokenId);
    }

    function removeFromAllTokens(uint256 tokenId) private {
        uint256 lastTokenIndex = allTokens.length - 1;
        uint256 tokenIndex = allTokensIndex[tokenId];
        uint256 lastTokenId = allTokens[lastTokenIndex];

        allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete allTokensIndex[tokenId];
        allTokens.pop();
    }

    /**
     * @dev Internal function to burn a specific token
     * Reverts if the token does not exist
     * @param _tokenId uint256 ID of the token being burned by the msg.sender
     */
    function _burn(address _owner, uint256 _tokenId)
        internal
        canTransfer(_tokenId)
    {
        clearApproval(_owner, _tokenId);
        removeTokenFrom(_owner, _tokenId);
        removeFromAllTokens(_tokenId);
        tokenOwner[_tokenId] = address(0);
        emit Transfer(_owner, address(0), _tokenId);
    }

    /**
     * @dev Internal function to clear current approval of a given token ID
     * Reverts if the given address is not indeed the owner of the token
     * @param _owner owner of the token
     * @param _tokenId uint256 ID of the token to be transferred
     */
    function clearApproval(address _owner, uint256 _tokenId) internal {
        require(
            ownerOf(_tokenId) == _owner,
            "Asset does not belong to given owmer"
        );
        if (tokenApprovals[_tokenId] != address(0)) {
            tokenApprovals[_tokenId] = address(0);
            emit Approval(_owner, address(0), _tokenId);
        }
    }

    /**
     * @dev Internal function to add a token ID to the list of a given address
     * @param _to address representing the new owner of the given token ID
     * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function addTokenTo(address _to, uint256 _tokenId) internal {
        uint256 length = balanceOf(_to);
        ownedTokens[_to][length] = _tokenId;
        ownedTokensIndex[_tokenId] = length;
        ownedTokensCount[_to] = ownedTokensCount[_to] + 1;  // increment balance of `_to` by 1
        tokenOwner[_tokenId] = _to; // assign `_to` as owner of token
    }

    /**
     * @dev Internal function to remove a token ID from the list of a given address
     * @param _from address representing the previous owner of the given token ID
     * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function removeTokenFrom(address _from, uint256 _tokenId) internal {
        uint256 lastTokenIndex = ownedTokensCount[_from] - 1;
        uint256 tokenIndex = ownedTokensIndex[_tokenId];

        // when we want to delete last token, the swap operation in unnecessary
        if(lastTokenIndex != tokenIndex) {
            uint256 lastTokenId = ownedTokens[_from][lastTokenIndex];
            ownedTokens[_from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }
        // This also deletes the contents at the last position of the array
        delete ownedTokensIndex[_tokenId];
        delete ownedTokens[_from][lastTokenIndex];
        ownedTokensCount[_from] = ownedTokensCount[_from]-1; // decrease balance of _from by 1
    }

    /**
     * @dev Internal function to invoke `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 whether the call correctly returned the expected magic value
     */
    function checkAndCallSafeTransfer(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) internal returns (bool) {
        if (!_to.isContract()) {
            return true;
        }
        bytes4 retval = ERC721Receiver(_to).onERC721Received(
            _from,
            _tokenId,
            _data
        );
        return (retval == ERC721_RECEIVED);
    }

    /**
     * @dev Gets the token ID at a given index of the tokens list of the requested owner
     * @param _owner address owning the tokens list to be accessed
     * @param _index uint256 representing the index to be accessed of the requested tokens list
     * @return uint256 token ID at the given index of the tokens list owned by the requested address
     */
    function tokenOfOwnerByIndex(address _owner, uint256 _index)
        public
        view
        returns (uint256)
    {
        require(_index < balanceOf(_owner), "Invalid index");
        return ownedTokens[_owner][_index];
    }

    /**
     * @dev Gets the total amount of tokens stored by the contract
     * @return uint256 representing the total amount of tokens
     */
    function totalSupply() public view returns (uint256) {
        return allTokens.length;
    }

    /**
     * @dev Gets the token ID at a given index of all the tokens in this contract
     * Reverts if the index is greater or equal to the total number of tokens
     * @param _index uint256 representing the index to be accessed of the tokens list
     * @return uint256 token ID at the given index of the tokens list
     */
    function tokenByIndex(uint256 _index) public view returns (uint256) {
        require(_index < totalSupply(), "Invalid index");
        return allTokens[_index];
    }

    function supportsInterface(bytes4 _interfaceId)
        external
        view
        returns (bool)
    {
        return supportedInterfaces[_interfaceId];
    }

    function _registerInterface(bytes4 _interfaceId) internal {
        require(_interfaceId != 0xffffffff);
        supportedInterfaces[_interfaceId] = true;
    }
}

File 3 of 9: ERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.16;

import "./BaseERC721.sol";

contract ERC721 is ERC721BasicToken {
    using Strings for uint256;

    mapping(uint256 => string) internal _tokenUri;
    string public extension;

    event TokenURIUpdated(uint256 tokenId, string _url);
    event BaseTokenURIUpdated(string _baseUrl);

    constructor(
        string memory _name,
        string memory _symbol,
        string memory _baseTokenUri,
        string memory _extension
    ) ERC721BasicToken(_name, _symbol, _baseTokenUri) {
        extension= _extension;
        emit BaseTokenURIUpdated(_baseTokenUri);
    }

    function approve(address _to, uint256 _tokenId) public {
        super._approve(_to, _tokenId);
    }

    function setApprovalForAll(address _to, bool _approved) public {
        super._setApprovalForAll(_to, _approved);
    }

    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public virtual {
        super._transferFrom(_from, _to, _tokenId);
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public virtual {
        super._safeTransferFrom(_from, _to, _tokenId, "0x");
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) public virtual {
        super._safeTransferFrom(_from, _to, _tokenId, _data);
    }

    function _updateTokenUri(uint256 _tokenId, string memory _url) internal {
        _tokenUri[_tokenId] = _url;
        emit TokenURIUpdated(_tokenId, _url);
    }

    function _updateBaseTokenUri(string memory _baseTokenUri) internal {
        baseTokenURI = _baseTokenUri;
        emit BaseTokenURIUpdated(_baseTokenUri);
    }

    function mint(
        address _to,
        uint256 _tokenId
    ) internal {
        super._mint(_to, _tokenId);
    }

    function burn(uint256 _tokenId) public virtual {
        super._burn(ownerOf(_tokenId), _tokenId);
    }

    function _tokenURI(uint256 _tokenId)
        public
        view
        virtual
        returns (string memory)
    {
        if (bytes(_tokenUri[_tokenId]).length == 0) {
            return string(abi.encodePacked(baseTokenURI, _tokenId.toString(), extension));
        }
        return string(abi.encodePacked(baseTokenURI, _tokenUri[_tokenId], extension));
    }
}

File 4 of 9: ERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.16;

/**
 * @title ERC721 token receiver interface
 * @author Prashant Prabhakar Singh [[email protected]]
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
abstract contract ERC721Receiver {
    /**
     * @dev Magic value to be returned upon successful reception of an NFT
     *  Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`,
     *  which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
     */
    bytes4 internal constant ERC721_RECEIVED = 0xf0b9e5ba;

    /**
     * @notice Handle the receipt of an NFT
     * @dev The ERC721 smart contract calls this function on the recipient
     * after a `safetransfer`. This function MAY throw to revert and reject the
     * transfer. This function MUST use 50,000 gas or less. Return of other
     * than the magic value MUST result in the transaction being reverted.
     * Note: the contract address is always the message sender.
     * @param _from The sending address
     * @param _tokenId The NFT identifier which is being transfered
     * @param _data Additional data with no specified format
     * @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
     */
    function onERC721Received(
        address _from,
        uint256 _tokenId,
        bytes memory _data
    ) public virtual returns (bytes4);
}

File 5 of 9: IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.16;

/**
 * @title ERC721 Non-Fungible Token Standard basic interface
 * @author Prashant Prabhakar Singh [[email protected]]
 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
interface IERC721 {
    event Transfer(
        address indexed _from,
        address indexed _to,
        uint256 indexed _tokenId
    );
    event Approval(
        address indexed _owner,
        address indexed _approved,
        uint256 indexed _tokenId
    );
    event ApprovalForAll(
        address indexed _owner,
        address indexed _operator,
        bool _approved
    );

    function balanceOf(address _owner) external view returns (uint256 _balance);

    function ownerOf(uint256 _tokenId) external view returns (address _owner);

    function exists(uint256 _tokenId) external view returns (bool _exists);

    function approve(address _to, uint256 _tokenId) external;

    function getApproved(uint256 _tokenId)
        external
        view
        returns (address _operator);

    function setApprovalForAll(address _operator, bool _approved) external;

    function isApprovedForAll(address _owner, address _operator)
        external
        view
        returns (bool);

    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) external;

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) external;

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) external;

    function name() external view returns (string memory _name);

    function symbol() external view returns (string memory _symbol);

    function tokenURI(uint256 _tokenId) external view returns (string memory);

    function totalSupply() external view returns (uint256);

    function tokenOfOwnerByIndex(address _owner, uint256 _index)
        external
        view
        returns (uint256 _tokenId);

    function tokenByIndex(uint256 _index) external view returns (uint256);

    function supportsInterface(bytes4 _interfaceId)
        external
        view
        returns (bool);
}

File 6 of 9: MintPassDummy.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.16;

import "./Ownership.sol";
import "./Addresses.sol";
import "./Strings.sol";
import "./ERC721Receiver.sol";
import "./IERC721.sol";

abstract contract ERC721BasicTokenDummy is IERC721 {
    using Address for address;
    using Strings for uint256;

    bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd;
    bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79;
    bytes4 private constant ERC721_RECEIVED = 0xf0b9e5ba;
    bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63;
    bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f;
    bytes4 private constant InterfaceId_ERC165 = 0x01ffc9a7;

    string internal name_;
    string internal symbol_;
    string public baseTokenURI;

    // Array with all token ids, used for enumeration
    uint256[] internal allTokens;

    // Mapping of interface id to whether or not it's supported
    mapping(bytes4 => bool) internal supportedInterfaces;

    // Mapping from owner to list of owned token IDs
    mapping(address => uint256[]) internal ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) internal ownedTokensIndex;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) internal allTokensIndex;

    // Mapping from token ID to owner
    mapping(uint256 => address) internal tokenOwner;

    // Mapping from token ID to approved address
    mapping(uint256 => address) internal tokenApprovals;

    // Mapping from owner to number of owned token
    mapping(address => uint256) internal ownedTokensCount;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) internal operatorApprovals;

    /**
     * @dev Guarantees msg.sender is owner of the given token
     * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender
     */
    modifier onlyOwnerOf(uint256 _tokenId) {
        require(ownerOf(_tokenId) == msg.sender, "Only asset owner is allowed");
        _;
    }

    /**
     * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator
     * @param _tokenId uint256 ID of the token to validate
     */
    modifier canTransfer(uint256 _tokenId) {
        require(isApprovedOrOwner(msg.sender, _tokenId), "Can not transfer");
        _;
    }

    constructor(
        string memory _name,
        string memory _symbol,
        string memory _baseTokenUri
    ) {
        name_ = _name;
        symbol_ = _symbol;
        baseTokenURI = _baseTokenUri;

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(InterfaceId_ERC721Enumerable);
        _registerInterface(InterfaceId_ERC721Metadata);
        _registerInterface(InterfaceId_ERC721);
        _registerInterface(InterfaceId_ERC721Exists);
        _registerInterface(InterfaceId_ERC165);
    }

    /**
     * @dev Gets the token name
     * @return string representing the token name
     */
    function name() external view returns (string memory) {
        return name_;
    }

    /**
     * @dev Gets the token symbol
     * @return string representing the token symbol
     */
    function symbol() external view returns (string memory) {
        return symbol_;
    }

    /**
     * @dev Returns an URI for a given token ID
     * Throws if the token ID does not exist. May return an empty string.
     * @param _tokenId uint256 ID of the token to query
     */
    function tokenURI(uint256 _tokenId)
        public
        view
        virtual
        returns (string memory)
    {
        require(exists(_tokenId), "Asset does not exist");
        return string(abi.encodePacked(baseTokenURI, _tokenId.toString()));
    }

    /**
     * @dev Gets the balance of the specified address
     * @param _owner address to query the balance of
     * @return uint256 representing the amount owned by the passed address
     */
    function balanceOf(address _owner) public view returns (uint256) {
        require(_owner != address(0), "Zero address not allowed");
        return ownedTokensCount[_owner];
    }

    /**
     * @dev Gets the owner of the specified token ID
     * @param _tokenId uint256 ID of the token to query the owner of
     * @return owner address currently marked as the owner of the given token ID
     */
    function ownerOf(uint256 _tokenId) public view returns (address) {
        address owner = tokenOwner[_tokenId];
        require(owner != address(0), "Zero address not allowed");
        return owner;
    }

    /**
     * @dev Returns whether the specified token exists
     * @param _tokenId uint256 ID of the token to query the existence of
     * @return whether the token exists
     */
    function exists(uint256 _tokenId) public view returns (bool) {
        address owner = tokenOwner[_tokenId];
        return owner != address(0);
    }

    /**
     * @dev Approves another address to transfer the given token ID
     * The zero address indicates there is no approved address.
     * There can only be one approved address per token at a given time.
     * Can only be called by the token owner or an approved operator.
     * @param _to address to be approved for the given token ID
     * @param _tokenId uint256 ID of the token to be approved
     */
    function _approve(address _to, uint256 _tokenId) internal {
        address owner = ownerOf(_tokenId);
        require(_to != owner, "Can not approve to self");
        require(
            msg.sender == owner || isApprovedForAll(owner, msg.sender),
            "Not allowed to update approvals"
        );

        tokenApprovals[_tokenId] = _to;
        emit Approval(owner, _to, _tokenId);
    }

    /**
     * @dev Gets the approved address for a token ID, or zero if no address set
     * @param _tokenId uint256 ID of the token to query the approval of
     * @return address currently approved for the given token ID
     */
    function getApproved(uint256 _tokenId) public view returns (address) {
        return tokenApprovals[_tokenId];
    }

    /**
     * @dev Sets or unsets the approval of a given operator
     * An operator is allowed to transfer all tokens of the sender on their behalf
     * @param _to operator address to set the approval
     * @param _approved representing the status of the approval to be set
     */
    function _setApprovalForAll(address _to, bool _approved) internal {
        require(_to != msg.sender, "Can not approve to self");
        operatorApprovals[msg.sender][_to] = _approved;
        emit ApprovalForAll(msg.sender, _to, _approved);
    }

    /**
     * @dev Tells whether an operator is approved by a given owner
     * @param _owner owner address which you want to query the approval of
     * @param _operator operator address which you want to query the approval of
     * @return bool whether the given operator is approved by the given owner
     */
    function isApprovedForAll(address _owner, address _operator)
        public
        view
        returns (bool)
    {
        return operatorApprovals[_owner][_operator];
    }

    /**
     * @dev Transfers the ownership of a given token ID to another address
     * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
     * Requires the msg sender to be the owner, approved, or operator
     * @param _from current owner of the token
     * @param _to address to receive the ownership of the given token ID
     * @param _tokenId uint256 ID of the token to be transferred
     */
    function _transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) internal canTransfer(_tokenId) {
        require(_from != address(0), "Zero address not allowed");
        require(_to != address(0), "Zero address not allowed");

        clearApproval(_from, _tokenId);
        removeTokenFrom(_from, _tokenId);
        addTokenTo(_to, _tokenId);

        emit Transfer(_from, _to, _tokenId);
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     *
     * Requires the msg sender to be the owner, approved, or operator
     * @param _from current owner of the token
     * @param _to address to receive the ownership of the given token ID
     * @param _tokenId uint256 ID of the token to be transferred
     */
    function _safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) internal canTransfer(_tokenId) {
        // solium-disable-next-line arg-overflow
        _safeTransferFrom(_from, _to, _tokenId, "");
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg sender to be the owner, approved, or operator
     * @param _from current owner of the token
     * @param _to address to receive the ownership of the given token ID
     * @param _tokenId uint256 ID of the token to be transferred
     * @param _data bytes data to send along with a safe transfer check
     */
    function _safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) internal canTransfer(_tokenId) {
        _transferFrom(_from, _to, _tokenId);
        // solium-disable-next-line arg-overflow
        require(
            checkAndCallSafeTransfer(_from, _to, _tokenId, _data),
            "Safe Transfer failed"
        );
    }

    /**
     * @dev Returns whether the given spender can transfer a given token ID
     * @param _spender address of the spender to query
     * @param _tokenId uint256 ID of the token to be transferred
     * @return bool whether the msg.sender is approved for the given token ID,
     *  is an operator of the owner, or is the owner of the token
     */
    function isApprovedOrOwner(address _spender, uint256 _tokenId)
        internal
        view
        returns (bool)
    {
        address owner = ownerOf(_tokenId);
        // Disable solium check because of
        // https://github.com/duaraghav8/Solium/issues/175
        // solium-disable-next-line operator-whitespace
        return (_spender == owner ||
            getApproved(_tokenId) == _spender ||
            isApprovedForAll(owner, _spender));
    }

    /**
     * @dev Internal function to mint a new token
     * Reverts if the given token ID already exists
     * @param _to The address that will own the minted token
     * @param _tokenId uint256 ID of the token to be minted by the msg.sender
     */
    function _mint(address _to, uint256 _tokenId) internal {
        require(_to != address(0), "Zero address not allowed");
        addTokenTo(_to, _tokenId);
        allTokensIndex[_tokenId] = allTokens.length;
        allTokens.push(_tokenId);

        emit Transfer(address(0), _to, _tokenId);
    }

    /**
     * @dev Internal function to burn a specific token
     * Reverts if the token does not exist
     * @param _tokenId uint256 ID of the token being burned by the msg.sender
     */
    function _burn(address _owner, uint256 _tokenId)
        internal
        canTransfer(_tokenId)
    {
        clearApproval(_owner, _tokenId);
        removeTokenFrom(_owner, _tokenId);

        // Reorg all tokens array
        uint256 tokenIndex = allTokensIndex[_tokenId];
        uint256 lastTokenIndex = allTokens.length - 1;
        uint256 lastToken = allTokens[lastTokenIndex];

        allTokens[tokenIndex] = lastToken;
        delete allTokens[lastTokenIndex];

        //allTokens[lastTokenIndex] = 0;
        // allTokens.length--; // @TODO

        allTokensIndex[_tokenId] = 0;
        allTokensIndex[lastToken] = tokenIndex;
        emit Transfer(_owner, address(0), _tokenId);
    }

    /**
     * @dev Internal function to clear current approval of a given token ID
     * Reverts if the given address is not indeed the owner of the token
     * @param _owner owner of the token
     * @param _tokenId uint256 ID of the token to be transferred
     */
    function clearApproval(address _owner, uint256 _tokenId) internal {
        require(
            ownerOf(_tokenId) == _owner,
            "Asset does not belong to given owmer"
        );
        if (tokenApprovals[_tokenId] != address(0)) {
            tokenApprovals[_tokenId] = address(0);
            emit Approval(_owner, address(0), _tokenId);
        }
    }

    /**
     * @dev Internal function to add a token ID to the list of a given address
     * @param _to address representing the new owner of the given token ID
     * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function addTokenTo(address _to, uint256 _tokenId) internal {
        require(tokenOwner[_tokenId] == address(0), "Asset already exists");
        tokenOwner[_tokenId] = _to;
        ownedTokensCount[_to] = ownedTokensCount[_to] + 1;
        uint256 length = ownedTokens[_to].length;
        ownedTokens[_to].push(_tokenId);
        ownedTokensIndex[_tokenId] = length;
    }

    /**
     * @dev Internal function to remove a token ID from the list of a given address
     * @param _from address representing the previous owner of the given token ID
     * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function removeTokenFrom(address _from, uint256 _tokenId) internal {
        require(
            ownerOf(_tokenId) == _from,
            "Asset does not belong to given owmer"
        );
        ownedTokensCount[_from] = ownedTokensCount[_from] - 1;
        tokenOwner[_tokenId] = address(0);
        uint256 tokenIndex = ownedTokensIndex[_tokenId];
        uint256 lastTokenIndex = ownedTokens[_from].length - 1;
        uint256 lastToken = ownedTokens[_from][lastTokenIndex];

        ownedTokens[_from][tokenIndex] = lastToken;
        ownedTokens[_from][lastTokenIndex] = 0;
        // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to
        // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping
        // the lastToken to the first position, and then dropping the element placed in the last position of the list

        //ownedTokens[_from].length--; @TODO
        ownedTokensIndex[_tokenId] = 0;
        ownedTokensIndex[lastToken] = tokenIndex;
    }

    /**
     * @dev Internal function to invoke `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 whether the call correctly returned the expected magic value
     */
    function checkAndCallSafeTransfer(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) internal returns (bool) {
        if (!_to.isContract()) {
            return true;
        }
        bytes4 retval = ERC721Receiver(_to).onERC721Received(
            _from,
            _tokenId,
            _data
        );
        return (retval == ERC721_RECEIVED);
    }

    /**
     * @dev Gets the token ID at a given index of the tokens list of the requested owner
     * @param _owner address owning the tokens list to be accessed
     * @param _index uint256 representing the index to be accessed of the requested tokens list
     * @return uint256 token ID at the given index of the tokens list owned by the requested address
     */
    function tokenOfOwnerByIndex(address _owner, uint256 _index)
        public
        view
        returns (uint256)
    {
        require(_index < balanceOf(_owner), "Invalid index");
        return ownedTokens[_owner][_index];
    }

    /**
     * @dev Gets the total amount of tokens stored by the contract
     * @return uint256 representing the total amount of tokens
     */
    function totalSupply() public view returns (uint256) {
        return allTokens.length;
    }

    /**
     * @dev Gets the token ID at a given index of all the tokens in this contract
     * Reverts if the index is greater or equal to the total number of tokens
     * @param _index uint256 representing the index to be accessed of the tokens list
     * @return uint256 token ID at the given index of the tokens list
     */
    function tokenByIndex(uint256 _index) public view returns (uint256) {
        require(_index < totalSupply(), "Invalid index");
        return allTokens[_index];
    }

    function supportsInterface(bytes4 _interfaceId)
        external
        view
        returns (bool)
    {
        return supportedInterfaces[_interfaceId];
    }

    function _registerInterface(bytes4 _interfaceId) internal {
        require(_interfaceId != 0xffffffff);
        supportedInterfaces[_interfaceId] = true;
    }
}

contract ERC721Dummy is ERC721BasicTokenDummy {
    mapping(uint256 => string) internal _tokenUri;

    event TokenURIUpdated(uint256 tokenId, string _url);
    event BaseTokenURIUpdated(string _baseUrl);

    constructor(
        string memory _name,
        string memory _symbol,
        string memory _baseTokenUri
    ) ERC721BasicTokenDummy(_name, _symbol, _baseTokenUri) {
        emit BaseTokenURIUpdated(_baseTokenUri);
    }

    function approve(address _to, uint256 _tokenId) public {
        super._approve(_to, _tokenId);
    }

    function setApprovalForAll(address _to, bool _approved) public {
        super._setApprovalForAll(_to, _approved);
    }

    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public virtual {
        super._transferFrom(_from, _to, _tokenId);
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public virtual {
        super._safeTransferFrom(_from, _to, _tokenId, "0x");
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) public virtual {
        super._safeTransferFrom(_from, _to, _tokenId, _data);
    }

    function _updateTokenUri(uint256 _tokenId, string memory _url) internal {
        _tokenUri[_tokenId] = _url;
        emit TokenURIUpdated(_tokenId, _url);
    }

    function _updateBaseTokenUri(string memory _baseTokenUri) internal {
        baseTokenURI = _baseTokenUri;
        emit BaseTokenURIUpdated(_baseTokenUri);
    }

    function mint(
        address _to,
        uint256 _tokenId,
        string memory _url
    ) internal {
        _updateTokenUri(_tokenId, _url);
        super._mint(_to, _tokenId);
    }

    function burn(uint256 _tokenId) public virtual {
        super._burn(ownerOf(_tokenId), _tokenId);
    }

    function tokenURI(uint256 _tokenId)
        public
        view
        override
        returns (string memory)
    {
        require(exists(_tokenId), "Asset does not exist");
        return string(abi.encodePacked(baseTokenURI, _tokenUri[_tokenId]));
    }
}

contract MintPass is ERC721Dummy, Ownership {
    // represents how many times a mint pass is redeemed.
    mapping(uint256 => uint8) private redeemedTimes;
    // contracts that can update mint pass uses, like when minting art, art nft will updated `redeemedTimes`
    mapping(address => bool) public isWhitelisted;
    // nonce to prevent replay attack on admin signature
    mapping(uint256 => bool) public isSignerNonceUsed;

    bool public mintStoppted; // when enabled no futher mint pass can be minted.
    uint256 public maxSupply; // max supply of mint pass
    bool public isPaused = false; // pause the contractn when something goes "really" wrong

    uint8 constant UINT8_MAX = 255;

    struct Signature {
        bytes32 r;
        bytes32 s;
        uint8 v;
    }

    event MintPassUpdated(
        uint256 tokenId,
        uint8 redeemedTimes,
        address updatedBy
    );

    event Paused(bool _isPaused);

    modifier canAcceptMintPass(address user) {
        require(balanceOf(user) == 0, "Only 1 mint pass allowed per user");
        _;
    }

    modifier mintAllowed() {
        require(!mintStoppted, "Minting stopped");
        _;
    }

    modifier notPaused() {
        require(!isPaused, "Contract paused");
        _;
    }

    constructor(string memory _baseTokenUri)
        ERC721Dummy("Thunderbirds: IRC Mint Pass", "TBMP", _baseTokenUri)
    {
        maxSupply = 1000;
    }

    function mint(
        address user,
        Signature memory adminSignature,
        uint256 signerNonce
    ) public canAcceptMintPass(user) mintAllowed notPaused {
        require(totalSupply() < maxSupply, "Max token minted");
        require(
            !isSignerNonceUsed[signerNonce],
            "Duplicate nonce in signature"
        );
        bytes32 hash = keccak256(
            abi.encodePacked(
                bytes4(keccak256("mint")),
                address(this),
                signerNonce,
                getChainID(),
                user
            )
        );
        address signer = getSigner(hash, adminSignature);
        require(isDeputyOwner[signer], "Invalid signature/message");
        isSignerNonceUsed[signerNonce] = true;
        string memory url = "QmXyV2HUP7hv8Xjx3X6ZLUUMHkxsdRuQhZ9DwpzZqH16jD";
        super.mint(user, totalSupply() + 1, url);
    }

    function batchMintByAdmin(address[] memory users) public mintAllowed onlyDeputyOrOwner {
        require(totalSupply() + users.length < maxSupply, "Max token minted");
        string memory url = "QmXyV2HUP7hv8Xjx3X6ZLUUMHkxsdRuQhZ9DwpzZqH16jD";
        for(uint8 i=0; i<users.length; i++) {
            require(balanceOf(users[i]) == 0, "Only 1 mint pass allowed per user");
            super.mint(users[i], totalSupply() + 1, url);
        }
    }

    function updateRedeemedTimes(uint256 tokenId, uint8 _redeemedTimes)
        public
        notPaused
    {
        require(isWhitelisted[msg.sender], "Caller not whitelisted");
        redeemedTimes[tokenId] = _redeemedTimes;
        emit MintPassUpdated(tokenId, _redeemedTimes, msg.sender);
    }

    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public override canAcceptMintPass(_to) notPaused {
        super._transferFrom(_from, _to, _tokenId);
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    ) public override canAcceptMintPass(_to) notPaused {
        super._safeTransferFrom(_from, _to, _tokenId, "0x");
    }

    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _tokenId,
        bytes memory _data
    ) public override canAcceptMintPass(_to) notPaused {
        super._safeTransferFrom(_from, _to, _tokenId, _data);
    }

    function burn(uint256 _tokenId) public override notPaused {
        super.burn(_tokenId);
    }
    

    function updateTokenUri(uint256 _tokenId, string memory _url)
        public
        onlyDeputyOrOwner
    {
        super._updateTokenUri(_tokenId, _url);
    }

    function updateBaseTokenUri(string memory _baseTokenUri) public onlyOwner {
        super._updateBaseTokenUri(_baseTokenUri);
    }

    function whitelistContract(address contractAddress) public onlyOwner {
        isWhitelisted[contractAddress] = true;
    }

    function removeFromWhitelist(address contractAddress) public onlyOwner {
        isWhitelisted[contractAddress] = false;
    }

    function disableMinting(bool shoudlStop) public onlyOwner {
        mintStoppted = shoudlStop;
    }

    function pauseContract(bool _isPaused) public onlyOwner returns (bool) {
        isPaused = _isPaused;
        emit Paused(_isPaused);
        return true;
    }

    function getSigner(bytes32 message, Signature memory sig)
        public
        pure
        returns (address)
    {
        bytes memory prefix = "\x19Ethereum Signed Message:\n32";
        bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, message));
        address signer = ecrecover(prefixedHash, sig.v, sig.r, sig.s);
        return signer;
    }

    function getRedeemedTimes(uint256 tokenId) public view returns(uint8) {
        if(!exists(tokenId)) return UINT8_MAX;
        return redeemedTimes[tokenId];
    }

    function getChainID() internal view returns (uint256) {
        uint256 id;
        assembly {
            id := chainid()
        }
        return id;
    }
}

File 7 of 9: Ownership.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.16;

contract Ownership {
    address public owner;
    address[] public deputyOwners;

    mapping(address => bool) public isDeputyOwner;

    event OwnershipUpdated(address oldOwner, address newOwner);
    event DeputyOwnerUpdated(address _do, bool _isAdded);

    constructor() {
        owner = msg.sender;
        addDeputyOwner(msg.sender);
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Caller is not owner");
        _;
    }

    modifier onlyDeputyOrOwner() {
        require(
            msg.sender == owner || isDeputyOwner[msg.sender],
            "Caller is not owner or deputy"
        );
        _;
    }

    /**
     * @dev Transfer the ownership to some other address.
     * new owner can not be a zero address.
     * Only owner can call this function
     * @param _newOwner Address to which ownership is being transferred
     */
    function updateOwner(address _newOwner) public onlyOwner {
        require(_newOwner != address(0x0), "Invalid address");
        owner = _newOwner;
        emit OwnershipUpdated(msg.sender, owner);
    }

    /**
     * @dev Add new deputy owner.
     * Only Owner can call this function
     * New Deputy should not be zero address
     * New Deputy should not be be already exisitng
     * emit DeputyOwnerUdpatd event
     * @param _newDO Address of new deputy owner
     */
    function addDeputyOwner(address _newDO) public onlyOwner {
        require(!isDeputyOwner[_newDO], "Deputy Owner already exists");
        deputyOwners.push(_newDO);
        isDeputyOwner[_newDO] = true;
        emit DeputyOwnerUpdated(_newDO, true);
    }

    /**
     * @dev Remove an existing deputy owner.
     * Only Owner can call this function
     * Given address should be a deputy owner
     * emit DeputyOwnerUdpatd event
     * @param _existingDO Address of existing deputy owner
     */
    function removeDeputyOwner(address _existingDO) public onlyOwner {
        require(isDeputyOwner[_existingDO], "Deputy Owner does not exits");
        uint256 existingId;
        for (uint256 i = 0; i < deputyOwners.length; i++) {
            if (deputyOwners[i] == _existingDO) existingId = i;
        }

        // swap this with last element
        deputyOwners[existingId] = deputyOwners[deputyOwners.length - 1];
        delete deputyOwners[deputyOwners.length - 1];
        isDeputyOwner[_existingDO] = false;
        emit DeputyOwnerUpdated(_existingDO, false);
    }

    /**
     * @dev Renounce the ownership.
     * This will leave the contract without any owner.
     * Only owner can call this function
     * @param _validationCode A code to prevent accidental calling of this function
     */
    function renounceOwnership(uint256 _validationCode) public onlyOwner {
        require(_validationCode == 123456789, "Invalid code");
        owner = address(0);
        emit OwnershipUpdated(msg.sender, owner);
    }
}

File 8 of 9: Strings.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.16;

/**
 * @dev String operations.
 */
library Strings {
    /**
     * @dev Converts a `uint256` to its ASCII `string` 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);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_mintPassContract","type":"address"},{"internalType":"uint256","name":"_preSaleStarts","type":"uint256"},{"internalType":"uint256","name":"_preSaleEnds","type":"uint256"},{"internalType":"address payable","name":"_coldWallet","type":"address"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"string","name":"_baseurl","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"string","name":"_baseUrl","type":"string"}],"name":"BaseTokenURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_do","type":"address"},{"indexed":false,"internalType":"bool","name":"_isAdded","type":"bool"}],"name":"DeputyOwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_isPaused","type":"bool"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"PriceUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"_url","type":"string"}],"name":"TokenURIUpdated","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"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"_tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newDO","type":"address"}],"name":"addDeputyOwner","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":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"coldWallet","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"deputyOwners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extension","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"bytes32","name":"message","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct Thunderbirds.Signature","name":"sig","type":"tuple"}],"name":"getSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","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":[{"internalType":"address","name":"","type":"address"}],"name":"isDeputyOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","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":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"isSignerNonceUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint8","name":"quantity","type":"uint8"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"}],"name":"mintReservedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint8","name":"quantity","type":"uint8"},{"internalType":"uint256","name":"mintPassId","type":"uint256"}],"name":"mintWithPass","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintedForTeam","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":[{"internalType":"bool","name":"_isPaused","type":"bool"}],"name":"pauseContract","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":"uint256","name":"signerNonce","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct Thunderbirds.Signature","name":"signature","type":"tuple"}],"name":"preAuthTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"preSaleEnds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preSaleStarts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_existingDO","type":"address"}],"name":"removeDeputyOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_validationCode","type":"uint256"}],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reveal","outputs":[],"stateMutability":"nonpayable","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":"saleEnds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","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":"string","name":"_baseTokenUri","type":"string"}],"name":"updateBaseTokenUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"updateOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"updatePrice","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526015805460ff60a01b191690553480156200001e57600080fd5b5060405162003a9138038062003a918339810160408190526200004191620003ff565b60405180606001604052806026815260200162003a6b60269139604051806040016040528060038152602001622320a160e91b8152508260405180604001604052806005815260200164173539b7b760d91b8152508383838260009081620000aa919062000590565b506001620000b9838262000590565b506002620000c8828262000590565b50620000db63780e9d6360e01b62000203565b620000ed635b5e139f60e01b62000203565b620000ff6380ac58cd60e01b62000203565b62000111634f558e7960e01b62000203565b620001236301ffc9a760e01b62000203565b50600d9150620001369050828262000590565b507fe6e4cd5c2dc7d2c20519b41832cd550fd3ea1186bf299d108179bf71fb8e00e5826040516200016891906200065c565b60405180910390a15050600e80546001600160a01b03191633908117909155620001959250905062000240565b601580546001600160a01b038089166001600160a01b0319928316179092556115386011556016849055601780549286169290911691909117905560128590556013849055620001e98462093a8062000691565b60145550506019805460ff1916905550620006b992505050565b6001600160e01b031980821690036200021b57600080fd5b6001600160e01b0319166000908152600460205260409020805460ff19166001179055565b600e546001600160a01b03163314620002a05760405162461bcd60e51b815260206004820152601360248201527f43616c6c6572206973206e6f74206f776e65720000000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b03811660009081526010602052604090205460ff16156200030b5760405162461bcd60e51b815260206004820152601b60248201527f446570757479204f776e657220616c7265616479206578697374730000000000604482015260640162000297565b600f805460018082019092557f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020180546001600160a01b0319166001600160a01b038416908117909155600081815260106020908152604091829020805460ff19168517905581519283528201929092527f3c3909677f69a0291b873bdd830b78dfb231df51c82872fde8d546da7cf85533910160405180910390a150565b6001600160a01b0381168114620003c057600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620003f6578181015183820152602001620003dc565b50506000910152565b60008060008060008060c087890312156200041957600080fd5b86516200042681620003aa565b80965050602087015194506040870151935060608701516200044881620003aa565b608088015160a089015191945092506001600160401b03808211156200046d57600080fd5b818901915089601f8301126200048257600080fd5b815181811115620004975762000497620003c3565b604051601f8201601f19908116603f01168101908382118183101715620004c257620004c2620003c3565b816040528281528c6020848701011115620004dc57600080fd5b620004ef836020830160208801620003d9565b80955050505050509295509295509295565b600181811c908216806200051657607f821691505b6020821081036200053757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200058b57600081815260208120601f850160051c81016020861015620005665750805b601f850160051c820191505b81811015620005875782815560010162000572565b5050505b505050565b81516001600160401b03811115620005ac57620005ac620003c3565b620005c481620005bd845462000501565b846200053d565b602080601f831160018114620005fc5760008415620005e35750858301515b600019600386901b1c1916600185901b17855562000587565b600085815260208120601f198616915b828110156200062d578886015182559484019460019091019084016200060c565b50858210156200064c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082518060208401526200067d816040850160208701620003d9565b601f01601f19169190910160400192915050565b80820180821115620006b357634e487b7160e01b600052601160045260246000fd5b92915050565b6133a280620006c96000396000f3fe6080604052600436106102885760003560e01c806376c16f991161015a578063b187bd26116100c1578063d547cfb71161007a578063d547cfb7146107e8578063d5abeb01146107fd578063e272b89214610813578063e985e9c514610833578063eaec357514610853578063f0ef95021461087357600080fd5b8063b187bd2614610731578063b616cbb514610752578063b88d4fde14610768578063c400956a14610788578063c87b56dd146107a8578063ca00043d146107c857600080fd5b80638da5cb5b116101135780638da5cb5b1461069157806395d89b41146106b1578063a035b1fe146106c6578063a22cb465146106dc578063a33cdc41146106fc578063a475b5dd1461071c57600080fd5b806376c16f99146105b65780637d654c7f146105d6578063880cdc31146105f657806389f8d150146106165780638d17e712146106515780638d6cc56d1461067157600080fd5b806342842e0e116101fe5780635533f19a116101b75780635533f19a1461050d578063558fc5e1146105235780636352211e14610543578063691562a0146105635780636be13c921461057657806370a082311461059657600080fd5b806342842e0e1461044857806342966c68146104685780634a75d91f146104885780634f558e791461049b5780634f6ccce7146104d357806354214f69146104f357600080fd5b806318160ddd1161025057806318160ddd1461039e5780631ae7e2ea146103bd57806323b872dd146103dd5780632d5537b0146103fd5780632f745c591461041257806332f654f61461043257600080fd5b806301ffc9a71461028d57806306fdde03146102dc578063081812fc146102fe578063095ea7b31461034c57806315761f0e1461036e575b600080fd5b34801561029957600080fd5b506102c76102a8366004612986565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b3480156102e857600080fd5b506102f1610889565b6040516102d391906129fa565b34801561030a57600080fd5b50610334610319366004612a0d565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b0390911681526020016102d3565b34801561035857600080fd5b5061036c610367366004612a3b565b61091b565b005b34801561037a57600080fd5b506102c7610389366004612a67565b60106020526000908152604090205460ff1681565b3480156103aa57600080fd5b506003545b6040519081526020016102d3565b3480156103c957600080fd5b5061036c6103d8366004612b40565b610929565b3480156103e957600080fd5b5061036c6103f8366004612b9c565b610b18565b34801561040957600080fd5b506102f1610b52565b34801561041e57600080fd5b506103af61042d366004612a3b565b610be0565b34801561043e57600080fd5b506103af60185481565b34801561045457600080fd5b5061036c610463366004612b9c565b610c55565b34801561047457600080fd5b5061036c610483366004612a0d565b610ca5565b61036c610496366004612bdd565b610cdb565b3480156104a757600080fd5b506102c76104b6366004612a0d565b6000908152600860205260409020546001600160a01b0316151590565b3480156104df57600080fd5b506103af6104ee366004612a0d565b61114f565b3480156104ff57600080fd5b506019546102c79060ff1681565b34801561051957600080fd5b506103af60145481565b34801561052f57600080fd5b5061036c61053e366004612c65565b6111bd565b34801561054f57600080fd5b5061033461055e366004612a0d565b6111f0565b61036c610571366004612cae565b61124d565b34801561058257600080fd5b50601754610334906001600160a01b031681565b3480156105a257600080fd5b506103af6105b1366004612a67565b611452565b3480156105c257600080fd5b5061036c6105d1366004612a67565b611496565b3480156105e257600080fd5b5061036c6105f1366004612a0d565b61168e565b34801561060257600080fd5b5061036c610611366004612a67565b611747565b34801561062257600080fd5b506102c7610631366004612a3b565b601a60209081526000928352604080842090915290825290205460ff1681565b34801561065d57600080fd5b506102f161066c366004612a0d565b61180e565b34801561067d57600080fd5b5061036c61068c366004612a0d565b611892565b34801561069d57600080fd5b50600e54610334906001600160a01b031681565b3480156106bd57600080fd5b506102f16118fd565b3480156106d257600080fd5b506103af60165481565b3480156106e857600080fd5b5061036c6106f7366004612cf5565b61190c565b34801561070857600080fd5b5061036c610717366004612a67565b611916565b34801561072857600080fd5b5061036c611a42565b34801561073d57600080fd5b506015546102c790600160a01b900460ff1681565b34801561075e57600080fd5b506103af60125481565b34801561077457600080fd5b5061036c610783366004612d23565b611a7b565b34801561079457600080fd5b506103346107a3366004612a0d565b611ab7565b3480156107b457600080fd5b506102f16107c3366004612a0d565b611ae1565b3480156107d457600080fd5b506103346107e3366004612da3565b611be4565b3480156107f457600080fd5b506102f1611ccd565b34801561080957600080fd5b506103af60115481565b34801561081f57600080fd5b5061036c61082e366004612dd0565b611cda565b34801561083f57600080fd5b506102c761084e366004612ded565b611d51565b34801561085f57600080fd5b5061036c61086e366004612e1b565b611d7f565b34801561087f57600080fd5b506103af60135481565b60606000805461089890612ecd565b80601f01602080910402602001604051908101604052809291908181526020018280546108c490612ecd565b80156109115780601f106108e657610100808354040283529160200191610911565b820191906000526020600020905b8154815290600101906020018083116108f457829003601f168201915b5050505050905090565b6109258282611eb7565b5050565b601554600160a01b900460ff161561095c5760405162461bcd60e51b815260040161095390612f07565b60405180910390fd5b6001600160a01b0385166000908152601a6020908152604080832085845290915290205460ff16156109d05760405162461bcd60e51b815260206004820152601c60248201527f4475706c6963617465206e6f6e636520696e207369676e6174757265000000006044820152606401610953565b60007fb483afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e3084466040516001600160e01b031990941660208501526bffffffffffffffffffffffff19606093841b811660248601526038850192909252605884015288821b811660788401529087901b16608c82015260a0810185905260c0016040516020818303038152906040528051906020012090506000610a738284611be4565b9050866001600160a01b0316816001600160a01b031614610ad65760405162461bcd60e51b815260206004820152601c60248201527f4f776e657220616e64207369676e657220646f6e2774206d61746368000000006044820152606401610953565b6001600160a01b0381166000908152601a602090815260408083208784529091529020805460ff19166001179055610b0f818787611fe3565b50505050505050565b601554600160a01b900460ff1615610b425760405162461bcd60e51b815260040161095390612f07565b610b4d838383612014565b505050565b600d8054610b5f90612ecd565b80601f0160208091040260200160405190810160405280929190818152602001828054610b8b90612ecd565b8015610bd85780601f10610bad57610100808354040283529160200191610bd8565b820191906000526020600020905b815481529060010190602001808311610bbb57829003601f168201915b505050505081565b6000610beb83611452565b8210610c295760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610953565b506001600160a01b03821660009081526005602090815260408083208484529091529020545b92915050565b601554600160a01b900460ff1615610c7f5760405162461bcd60e51b815260040161095390612f07565b610b4d83838360405180604001604052806002815260200161060f60f31b815250612046565b601554600160a01b900460ff1615610ccf5760405162461bcd60e51b815260040161095390612f07565b610cd8816120a0565b50565b81601254421015610d225760405162461bcd60e51b815260206004820152601160248201527014d85b19481b9bdd081b1a5d99481e595d607a1b6044820152606401610953565b6014544210610d615760405162461bcd60e51b815260206004820152600b60248201526a14d85b194818db1bdcd95960aa1b6044820152606401610953565b601e601154610d709190612f46565b8160ff16610d7d60035490565b610d879190612f59565b1115610dc05760405162461bcd60e51b815260206004820152600860248201526714dbdb19081bdd5d60c21b6044820152606401610953565b8060ff16601654610dd19190612f6c565b3414610e0f5760405162461bcd60e51b815260206004820152600d60248201526c496e636f72726563742066656560981b6044820152606401610953565b6013544210610e515760405162461bcd60e51b815260206004820152600e60248201526d141c994b5cd85b1948195b99195960921b6044820152606401610953565b601554604051634f558e7960e01b8152600481018490526001600160a01b0390911690634f558e7990602401602060405180830381865afa158015610e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebe9190612f8b565b610efe5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964206d696e74207061737360781b6044820152606401610953565b6015546040516331a9108f60e11b81526004810184905233916001600160a01b031690636352211e90602401602060405180830381865afa158015610f47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6b9190612fa8565b6001600160a01b031614610fcd5760405162461bcd60e51b815260206004820152602360248201527f53656e64657220646f6573206e6f74206f776e20676976656e206d696e74207060448201526261737360e81b6064820152608401610953565b6017546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015611006573d6000803e3d6000fd5b5060155460405163fef59ea560e01b8152600481018490526000916001600160a01b03169063fef59ea590602401602060405180830381865afa158015611051573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110759190612fc5565b905060036110838583612fe2565b60ff1611156110c95760405162461bcd60e51b8152602060048201526012602482015271135a5b9d081c185cdcc81c995919595b595960721b6044820152606401610953565b6015546001600160a01b0316639c4d09a8846110e58785612fe2565b6040516001600160e01b031960e085901b168152600481019290925260ff166024820152604401600060405180830381600087803b15801561112657600080fd5b505af115801561113a573d6000803e3d6000fd5b5050505061114885856120b2565b5050505050565b600061115a60035490565b82106111985760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610953565b600382815481106111ab576111ab612ffb565b90600052602060002001549050919050565b600e546001600160a01b031633146111e75760405162461bcd60e51b815260040161095390613011565b610cd8816120e2565b6000818152600860205260408120546001600160a01b031680610c4f5760405162461bcd60e51b8152602060048201526015602482015274546f6b656e20646f6573206e6f742065786973747360581b6044820152606401610953565b806012544210156112945760405162461bcd60e51b815260206004820152601160248201527014d85b19481b9bdd081b1a5d99481e595d607a1b6044820152606401610953565b60145442106112d35760405162461bcd60e51b815260206004820152600b60248201526a14d85b194818db1bdcd95960aa1b6044820152606401610953565b601e6011546112e29190612f46565b8160ff166112ef60035490565b6112f99190612f59565b11156113325760405162461bcd60e51b815260206004820152600860248201526714dbdb19081bdd5d60c21b6044820152606401610953565b8060ff166016546113439190612f6c565b34146113815760405162461bcd60e51b815260206004820152600d60248201526c496e636f72726563742066656560981b6044820152606401610953565b601554600160a01b900460ff16156113ab5760405162461bcd60e51b815260040161095390612f07565b60135442101561140e5760405162461bcd60e51b815260206004820152602860248201527f4f6e6c79206d696e747061737320686f6c6465727320616c6c6f77656420696e6044820152672070726573616c6560c01b6064820152608401610953565b6017546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015611447573d6000803e3d6000fd5b50610b4d83836120b2565b60006001600160a01b03821661147a5760405162461bcd60e51b81526004016109539061303e565b506001600160a01b03166000908152600a602052604090205490565b600e546001600160a01b031633146114c05760405162461bcd60e51b815260040161095390613011565b6001600160a01b03811660009081526010602052604090205460ff166115285760405162461bcd60e51b815260206004820152601b60248201527f446570757479204f776e657220646f6573206e6f7420657869747300000000006044820152606401610953565b6000805b600f5481101561158357826001600160a01b0316600f828154811061155357611553612ffb565b6000918252602090912001546001600160a01b031603611571578091505b8061157b81613075565b91505061152c565b50600f805461159490600190612f46565b815481106115a4576115a4612ffb565b600091825260209091200154600f80546001600160a01b0390921691839081106115d0576115d0612ffb565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600f805461160990600190612f46565b8154811061161957611619612ffb565b600091825260208083209190910180546001600160a01b03191690556001600160a01b038416808352601082526040808420805460ff191690558051918252918101929092527f3c3909677f69a0291b873bdd830b78dfb231df51c82872fde8d546da7cf85533910160405180910390a15050565b600e546001600160a01b031633146116b85760405162461bcd60e51b815260040161095390613011565b8063075bcd15146116fa5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c696420636f646560a01b6044820152606401610953565b600e80546001600160a01b031916905560408051338152600060208201527f4c19d31874b3f8325813d90efdd10758f703ab99b84367f07276ecd2cd69c95d91015b60405180910390a150565b600e546001600160a01b031633146117715760405162461bcd60e51b815260040161095390613011565b6001600160a01b0381166117b95760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610953565b600e80546001600160a01b0319166001600160a01b0383169081179091556040805133815260208101929092527f4c19d31874b3f8325813d90efdd10758f703ab99b84367f07276ecd2cd69c95d910161173c565b6000818152600c6020526040902080546060919061182b90612ecd565b905060000361186957600261183f8361211e565b600d60405160200161185393929190613101565b6040516020818303038152906040529050919050565b6002600c6000848152602001908152602001600020600d60405160200161185393929190613134565b600e546001600160a01b031633146118bc5760405162461bcd60e51b815260040161095390613011565b60165460408051918252602082018390527f92664190cca12aca9cd5309d87194bdda75bb51362d71c06e1a6f75c7c765711910160405180910390a1601655565b60606001805461089890612ecd565b6109258282612227565b600e546001600160a01b031633146119405760405162461bcd60e51b815260040161095390613011565b6001600160a01b03811660009081526010602052604090205460ff16156119a95760405162461bcd60e51b815260206004820152601b60248201527f446570757479204f776e657220616c72656164792065786973747300000000006044820152606401610953565b600f805460018082019092557f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020180546001600160a01b0319166001600160a01b038416908117909155600081815260106020908152604091829020805460ff19168517905581519283528201929092527f3c3909677f69a0291b873bdd830b78dfb231df51c82872fde8d546da7cf85533910161173c565b600e546001600160a01b03163314611a6c5760405162461bcd60e51b815260040161095390613011565b6019805460ff19166001179055565b601554600160a01b900460ff1615611aa55760405162461bcd60e51b815260040161095390612f07565b611ab184848484612046565b50505050565b600f8181548110611ac757600080fd5b6000918252602090912001546001600160a01b0316905081565b6000818152600860205260409020546060906001600160a01b0316611b3f5760405162461bcd60e51b8152602060048201526014602482015273105cdcd95d08191bd95cc81b9bdd08195e1a5cdd60621b6044820152606401610953565b60195460ff16611bdb5760028054611b5690612ecd565b80601f0160208091040260200160405190810160405280929190818152602001828054611b8290612ecd565b8015611bcf5780601f10611ba457610100808354040283529160200191611bcf565b820191906000526020600020905b815481529060010190602001808311611bb257829003601f168201915b50505050509050919050565b610c4f8261180e565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250905060008185604051602001611c3492919061315b565b604051602081830303815290604052805190602001209050600060018286604001518760000151886020015160405160008152602001604052604051611c96949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611cb8573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60028054610b5f90612ecd565b600e546001600160a01b03163314611d045760405162461bcd60e51b815260040161095390613011565b60158054821515600160a01b0260ff60a01b199091161790556040517f0e2fb031ee032dc02d8011dc50b816eb450cf856abd8261680dac74f72165bd29061173c90831515815260200190565b6001600160a01b039182166000908152600b6020908152604080832093909416825291909152205460ff1690565b600e546001600160a01b0316331480611da757503360009081526010602052604090205460ff165b611df35760405162461bcd60e51b815260206004820152601d60248201527f43616c6c6572206973206e6f74206f776e6572206f72206465707574790000006044820152606401610953565b601e8151601854611e049190612f59565b1115611e525760405162461bcd60e51b815260206004820152601a60248201527f4d617820726573657276656420746f6b656e73206d696e7465640000000000006044820152606401610953565b805160188054909101905560005b81518160ff16101561092557611ea5828260ff1681518110611e8457611e84612ffb565b6020026020010151611e9560035490565b611ea0906001612f59565b6122e5565b80611eaf8161317d565b915050611e60565b6000611ec2826111f0565b9050806001600160a01b0316836001600160a01b031603611f1f5760405162461bcd60e51b815260206004820152601760248201527621b0b7103737ba1030b8383937bb32903a379039b2b63360491b6044820152606401610953565b336001600160a01b0382161480611f3b5750611f3b8133611d51565b611f875760405162461bcd60e51b815260206004820152601f60248201527f4e6f7420616c6c6f77656420746f2075706461746520617070726f76616c73006044820152606401610953565b60008281526009602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b611fed83826122ef565b6120095760405162461bcd60e51b81526004016109539061319c565b610b4d838383612346565b8061201f33826122ef565b61203b5760405162461bcd60e51b81526004016109539061319c565b611ab1848484612346565b612051848484612014565b61205d848484846123d0565b611ab15760405162461bcd60e51b815260206004820152601460248201527314d8599948151c985b9cd9995c8819985a5b195960621b6044820152606401610953565b610cd86120ac826111f0565b82612484565b60005b8160ff168160ff161015610b4d576120d083611e9560035490565b806120da8161317d565b9150506120b5565b60026120ee8282613214565b507fe6e4cd5c2dc7d2c20519b41832cd550fd3ea1186bf299d108179bf71fb8e00e58160405161173c91906129fa565b6060816000036121455750506040805180820190915260018152600360fc1b602082015290565b8160005b811561216f578061215981613075565b91506121689050600a836132ea565b9150612149565b60008167ffffffffffffffff81111561218a5761218a612a84565b6040519080825280601f01601f1916602001820160405280156121b4576020820181803683370190505b5090505b841561221f576121c9600183612f46565b91506121d6600a866132fe565b6121e1906030612f59565b60f81b8183815181106121f6576121f6612ffb565b60200101906001600160f81b031916908160001a905350612218600a866132ea565b94506121b8565b949350505050565b336001600160a01b038316036122795760405162461bcd60e51b815260206004820152601760248201527621b0b7103737ba1030b8383937bb32903a379039b2b63360491b6044820152606401610953565b336000818152600b602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610925828261251e565b6000806122fb836111f0565b9050806001600160a01b0316846001600160a01b0316148061233657506000838152600960205260409020546001600160a01b038581169116145b8061221f575061221f8185611d51565b6001600160a01b03821661236c5760405162461bcd60e51b81526004016109539061303e565b6123768382612628565b612380838261270f565b61238a82826127f2565b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60006123e4846001600160a01b0316612888565b6123f05750600161221f565b60405163785cf2dd60e11b81526000906001600160a01b0386169063f0b9e5ba9061242390899088908890600401613312565b6020604051808303816000875af1158015612442573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124669190613339565b6001600160e01b03191663785cf2dd60e11b14915050949350505050565b8061248f33826122ef565b6124ab5760405162461bcd60e51b81526004016109539061319c565b6124b58383612628565b6124bf838361270f565b6124c8826128c1565b60008281526008602052604080822080546001600160a01b0319169055518391906001600160a01b038616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a4505050565b6001600160a01b0382166125445760405162461bcd60e51b81526004016109539061303e565b6000818152600860205260409020546001600160a01b0316156125a05760405162461bcd60e51b8152602060048201526014602482015273417373657420616c72656164792065786973747360601b6044820152606401610953565b6125aa82826127f2565b600380546000838152600760205260408082208390556001830184559281527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b909101839055905182916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b816001600160a01b031661263b826111f0565b6001600160a01b03161461269d5760405162461bcd60e51b8152602060048201526024808201527f417373657420646f6573206e6f742062656c6f6e6720746f20676976656e206f6044820152633bb6b2b960e11b6064820152608401610953565b6000818152600960205260409020546001600160a01b0316156109255760008181526009602052604080822080546001600160a01b0319169055518291906001600160a01b038516907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908390a45050565b6001600160a01b0382166000908152600a602052604081205461273490600190612f46565b600083815260066020526040902054909150808214612787576001600160a01b03841660009081526005602090815260408083208584528252808320548484528184208190558352600690915290208190555b60008381526006602090815260408083208390556001600160a01b0387168084526005835281842086855283528184208490558352600a9091529020546127d090600190612f46565b6001600160a01b039094166000908152600a6020526040902093909355505050565b60006127fd83611452565b6001600160a01b0384166000818152600560209081526040808320858452825280832087905586835260068252808320859055928252600a90522054909150612847906001612f59565b6001600160a01b039093166000818152600a602090815260408083209690965593815260089093529290912080546001600160a01b03191690921790915550565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061221f575050151592915050565b6003546000906128d390600190612f46565b600083815260076020526040812054600380549394509092849081106128fb576128fb612ffb565b90600052602060002001549050806003838154811061291c5761291c612ffb565b600091825260208083209091019290925582815260079091526040808220849055858252812055600380548061295457612954613356565b6001900381819060005260206000200160009055905550505050565b6001600160e01b031981168114610cd857600080fd5b60006020828403121561299857600080fd5b81356129a381612970565b9392505050565b60005b838110156129c55781810151838201526020016129ad565b50506000910152565b600081518084526129e68160208601602086016129aa565b601f01601f19169290920160200192915050565b6020815260006129a360208301846129ce565b600060208284031215612a1f57600080fd5b5035919050565b6001600160a01b0381168114610cd857600080fd5b60008060408385031215612a4e57600080fd5b8235612a5981612a26565b946020939093013593505050565b600060208284031215612a7957600080fd5b81356129a381612a26565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612ac357612ac3612a84565b604052919050565b60ff81168114610cd857600080fd5b600060608284031215612aec57600080fd5b6040516060810181811067ffffffffffffffff82111715612b0f57612b0f612a84565b806040525080915082358152602083013560208201526040830135612b3381612acb565b6040919091015292915050565b600080600080600060e08688031215612b5857600080fd5b8535612b6381612a26565b94506020860135612b7381612a26565b93506040860135925060608601359150612b908760808801612ada565b90509295509295909350565b600080600060608486031215612bb157600080fd5b8335612bbc81612a26565b92506020840135612bcc81612a26565b929592945050506040919091013590565b600080600060608486031215612bf257600080fd5b8335612bfd81612a26565b92506020840135612bcc81612acb565b600067ffffffffffffffff831115612c2757612c27612a84565b612c3a601f8401601f1916602001612a9a565b9050828152838383011115612c4e57600080fd5b828260208301376000602084830101529392505050565b600060208284031215612c7757600080fd5b813567ffffffffffffffff811115612c8e57600080fd5b8201601f81018413612c9f57600080fd5b61221f84823560208401612c0d565b60008060408385031215612cc157600080fd5b8235612ccc81612a26565b91506020830135612cdc81612acb565b809150509250929050565b8015158114610cd857600080fd5b60008060408385031215612d0857600080fd5b8235612d1381612a26565b91506020830135612cdc81612ce7565b60008060008060808587031215612d3957600080fd5b8435612d4481612a26565b93506020850135612d5481612a26565b925060408501359150606085013567ffffffffffffffff811115612d7757600080fd5b8501601f81018713612d8857600080fd5b612d9787823560208401612c0d565b91505092959194509250565b60008060808385031215612db657600080fd5b82359150612dc78460208501612ada565b90509250929050565b600060208284031215612de257600080fd5b81356129a381612ce7565b60008060408385031215612e0057600080fd5b8235612e0b81612a26565b91506020830135612cdc81612a26565b60006020808385031215612e2e57600080fd5b823567ffffffffffffffff80821115612e4657600080fd5b818501915085601f830112612e5a57600080fd5b813581811115612e6c57612e6c612a84565b8060051b9150612e7d848301612a9a565b8181529183018401918481019088841115612e9757600080fd5b938501935b83851015612ec15784359250612eb183612a26565b8282529385019390850190612e9c565b98975050505050505050565b600181811c90821680612ee157607f821691505b602082108103612f0157634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600f908201526e10dbdb9d1c9858dd081c185d5cd959608a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c4f57610c4f612f30565b80820180821115610c4f57610c4f612f30565b6000816000190483118215151615612f8657612f86612f30565b500290565b600060208284031215612f9d57600080fd5b81516129a381612ce7565b600060208284031215612fba57600080fd5b81516129a381612a26565b600060208284031215612fd757600080fd5b81516129a381612acb565b60ff8181168382160190811115610c4f57610c4f612f30565b634e487b7160e01b600052603260045260246000fd5b60208082526013908201527221b0b63632b91034b9903737ba1037bbb732b960691b604082015260600190565b60208082526018908201527f5a65726f2061646472657373206e6f7420616c6c6f7765640000000000000000604082015260600190565b60006001820161308757613087612f30565b5060010190565b6000815461309b81612ecd565b600182811680156130b357600181146130c8576130f7565b60ff19841687528215158302870194506130f7565b8560005260208060002060005b858110156130ee5781548a8201529084019082016130d5565b50505082870194505b5050505092915050565b600061310d828661308e565b845161311d8183602089016129aa565b6131298183018661308e565b979650505050505050565b600061315261314c613146848861308e565b8661308e565b8461308e565b95945050505050565b6000835161316d8184602088016129aa565b9190910191825250602001919050565b600060ff821660ff810361319357613193612f30565b60010192915050565b60208082526010908201526f21b0b7103737ba103a3930b739b332b960811b604082015260600190565b601f821115610b4d57600081815260208120601f850160051c810160208610156131ed5750805b601f850160051c820191505b8181101561320c578281556001016131f9565b505050505050565b815167ffffffffffffffff81111561322e5761322e612a84565b6132428161323c8454612ecd565b846131c6565b602080601f831160018114613277576000841561325f5750858301515b600019600386901b1c1916600185901b17855561320c565b600085815260208120601f198616915b828110156132a657888601518255948401946001909101908401613287565b50858210156132c45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601260045260246000fd5b6000826132f9576132f96132d4565b500490565b60008261330d5761330d6132d4565b500690565b60018060a01b038416815282602082015260606040820152600061315260608301846129ce565b60006020828403121561334b57600080fd5b81516129a381612970565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220c98077b88d5b3c8a87e109dd5ec09e586b9eee9ad7d157be620b998fe081454164736f6c634300081000335468756e646572626972647320496e7465726e6174696f6e616c2052657363756520436c7562000000000000000000000000e65f378d11ba8ea0a1cc5223abc555fa1bbbe2ea000000000000000000000000000000000000000000000000000000006335a4e0000000000000000000000000000000000000000000000000000000006336f660000000000000000000000000347afa0934ac1b62cab4d68542aa130a6e802ca3000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d4e6f317257527856627750347a62717671704771763541677339713655325267624c7655616d3641546845380000000000000000000000

Deployed Bytecode

0x6080604052600436106102885760003560e01c806376c16f991161015a578063b187bd26116100c1578063d547cfb71161007a578063d547cfb7146107e8578063d5abeb01146107fd578063e272b89214610813578063e985e9c514610833578063eaec357514610853578063f0ef95021461087357600080fd5b8063b187bd2614610731578063b616cbb514610752578063b88d4fde14610768578063c400956a14610788578063c87b56dd146107a8578063ca00043d146107c857600080fd5b80638da5cb5b116101135780638da5cb5b1461069157806395d89b41146106b1578063a035b1fe146106c6578063a22cb465146106dc578063a33cdc41146106fc578063a475b5dd1461071c57600080fd5b806376c16f99146105b65780637d654c7f146105d6578063880cdc31146105f657806389f8d150146106165780638d17e712146106515780638d6cc56d1461067157600080fd5b806342842e0e116101fe5780635533f19a116101b75780635533f19a1461050d578063558fc5e1146105235780636352211e14610543578063691562a0146105635780636be13c921461057657806370a082311461059657600080fd5b806342842e0e1461044857806342966c68146104685780634a75d91f146104885780634f558e791461049b5780634f6ccce7146104d357806354214f69146104f357600080fd5b806318160ddd1161025057806318160ddd1461039e5780631ae7e2ea146103bd57806323b872dd146103dd5780632d5537b0146103fd5780632f745c591461041257806332f654f61461043257600080fd5b806301ffc9a71461028d57806306fdde03146102dc578063081812fc146102fe578063095ea7b31461034c57806315761f0e1461036e575b600080fd5b34801561029957600080fd5b506102c76102a8366004612986565b6001600160e01b03191660009081526004602052604090205460ff1690565b60405190151581526020015b60405180910390f35b3480156102e857600080fd5b506102f1610889565b6040516102d391906129fa565b34801561030a57600080fd5b50610334610319366004612a0d565b6000908152600960205260409020546001600160a01b031690565b6040516001600160a01b0390911681526020016102d3565b34801561035857600080fd5b5061036c610367366004612a3b565b61091b565b005b34801561037a57600080fd5b506102c7610389366004612a67565b60106020526000908152604090205460ff1681565b3480156103aa57600080fd5b506003545b6040519081526020016102d3565b3480156103c957600080fd5b5061036c6103d8366004612b40565b610929565b3480156103e957600080fd5b5061036c6103f8366004612b9c565b610b18565b34801561040957600080fd5b506102f1610b52565b34801561041e57600080fd5b506103af61042d366004612a3b565b610be0565b34801561043e57600080fd5b506103af60185481565b34801561045457600080fd5b5061036c610463366004612b9c565b610c55565b34801561047457600080fd5b5061036c610483366004612a0d565b610ca5565b61036c610496366004612bdd565b610cdb565b3480156104a757600080fd5b506102c76104b6366004612a0d565b6000908152600860205260409020546001600160a01b0316151590565b3480156104df57600080fd5b506103af6104ee366004612a0d565b61114f565b3480156104ff57600080fd5b506019546102c79060ff1681565b34801561051957600080fd5b506103af60145481565b34801561052f57600080fd5b5061036c61053e366004612c65565b6111bd565b34801561054f57600080fd5b5061033461055e366004612a0d565b6111f0565b61036c610571366004612cae565b61124d565b34801561058257600080fd5b50601754610334906001600160a01b031681565b3480156105a257600080fd5b506103af6105b1366004612a67565b611452565b3480156105c257600080fd5b5061036c6105d1366004612a67565b611496565b3480156105e257600080fd5b5061036c6105f1366004612a0d565b61168e565b34801561060257600080fd5b5061036c610611366004612a67565b611747565b34801561062257600080fd5b506102c7610631366004612a3b565b601a60209081526000928352604080842090915290825290205460ff1681565b34801561065d57600080fd5b506102f161066c366004612a0d565b61180e565b34801561067d57600080fd5b5061036c61068c366004612a0d565b611892565b34801561069d57600080fd5b50600e54610334906001600160a01b031681565b3480156106bd57600080fd5b506102f16118fd565b3480156106d257600080fd5b506103af60165481565b3480156106e857600080fd5b5061036c6106f7366004612cf5565b61190c565b34801561070857600080fd5b5061036c610717366004612a67565b611916565b34801561072857600080fd5b5061036c611a42565b34801561073d57600080fd5b506015546102c790600160a01b900460ff1681565b34801561075e57600080fd5b506103af60125481565b34801561077457600080fd5b5061036c610783366004612d23565b611a7b565b34801561079457600080fd5b506103346107a3366004612a0d565b611ab7565b3480156107b457600080fd5b506102f16107c3366004612a0d565b611ae1565b3480156107d457600080fd5b506103346107e3366004612da3565b611be4565b3480156107f457600080fd5b506102f1611ccd565b34801561080957600080fd5b506103af60115481565b34801561081f57600080fd5b5061036c61082e366004612dd0565b611cda565b34801561083f57600080fd5b506102c761084e366004612ded565b611d51565b34801561085f57600080fd5b5061036c61086e366004612e1b565b611d7f565b34801561087f57600080fd5b506103af60135481565b60606000805461089890612ecd565b80601f01602080910402602001604051908101604052809291908181526020018280546108c490612ecd565b80156109115780601f106108e657610100808354040283529160200191610911565b820191906000526020600020905b8154815290600101906020018083116108f457829003601f168201915b5050505050905090565b6109258282611eb7565b5050565b601554600160a01b900460ff161561095c5760405162461bcd60e51b815260040161095390612f07565b60405180910390fd5b6001600160a01b0385166000908152601a6020908152604080832085845290915290205460ff16156109d05760405162461bcd60e51b815260206004820152601c60248201527f4475706c6963617465206e6f6e636520696e207369676e6174757265000000006044820152606401610953565b60007fb483afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e3084466040516001600160e01b031990941660208501526bffffffffffffffffffffffff19606093841b811660248601526038850192909252605884015288821b811660788401529087901b16608c82015260a0810185905260c0016040516020818303038152906040528051906020012090506000610a738284611be4565b9050866001600160a01b0316816001600160a01b031614610ad65760405162461bcd60e51b815260206004820152601c60248201527f4f776e657220616e64207369676e657220646f6e2774206d61746368000000006044820152606401610953565b6001600160a01b0381166000908152601a602090815260408083208784529091529020805460ff19166001179055610b0f818787611fe3565b50505050505050565b601554600160a01b900460ff1615610b425760405162461bcd60e51b815260040161095390612f07565b610b4d838383612014565b505050565b600d8054610b5f90612ecd565b80601f0160208091040260200160405190810160405280929190818152602001828054610b8b90612ecd565b8015610bd85780601f10610bad57610100808354040283529160200191610bd8565b820191906000526020600020905b815481529060010190602001808311610bbb57829003601f168201915b505050505081565b6000610beb83611452565b8210610c295760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610953565b506001600160a01b03821660009081526005602090815260408083208484529091529020545b92915050565b601554600160a01b900460ff1615610c7f5760405162461bcd60e51b815260040161095390612f07565b610b4d83838360405180604001604052806002815260200161060f60f31b815250612046565b601554600160a01b900460ff1615610ccf5760405162461bcd60e51b815260040161095390612f07565b610cd8816120a0565b50565b81601254421015610d225760405162461bcd60e51b815260206004820152601160248201527014d85b19481b9bdd081b1a5d99481e595d607a1b6044820152606401610953565b6014544210610d615760405162461bcd60e51b815260206004820152600b60248201526a14d85b194818db1bdcd95960aa1b6044820152606401610953565b601e601154610d709190612f46565b8160ff16610d7d60035490565b610d879190612f59565b1115610dc05760405162461bcd60e51b815260206004820152600860248201526714dbdb19081bdd5d60c21b6044820152606401610953565b8060ff16601654610dd19190612f6c565b3414610e0f5760405162461bcd60e51b815260206004820152600d60248201526c496e636f72726563742066656560981b6044820152606401610953565b6013544210610e515760405162461bcd60e51b815260206004820152600e60248201526d141c994b5cd85b1948195b99195960921b6044820152606401610953565b601554604051634f558e7960e01b8152600481018490526001600160a01b0390911690634f558e7990602401602060405180830381865afa158015610e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebe9190612f8b565b610efe5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964206d696e74207061737360781b6044820152606401610953565b6015546040516331a9108f60e11b81526004810184905233916001600160a01b031690636352211e90602401602060405180830381865afa158015610f47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6b9190612fa8565b6001600160a01b031614610fcd5760405162461bcd60e51b815260206004820152602360248201527f53656e64657220646f6573206e6f74206f776e20676976656e206d696e74207060448201526261737360e81b6064820152608401610953565b6017546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015611006573d6000803e3d6000fd5b5060155460405163fef59ea560e01b8152600481018490526000916001600160a01b03169063fef59ea590602401602060405180830381865afa158015611051573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110759190612fc5565b905060036110838583612fe2565b60ff1611156110c95760405162461bcd60e51b8152602060048201526012602482015271135a5b9d081c185cdcc81c995919595b595960721b6044820152606401610953565b6015546001600160a01b0316639c4d09a8846110e58785612fe2565b6040516001600160e01b031960e085901b168152600481019290925260ff166024820152604401600060405180830381600087803b15801561112657600080fd5b505af115801561113a573d6000803e3d6000fd5b5050505061114885856120b2565b5050505050565b600061115a60035490565b82106111985760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610953565b600382815481106111ab576111ab612ffb565b90600052602060002001549050919050565b600e546001600160a01b031633146111e75760405162461bcd60e51b815260040161095390613011565b610cd8816120e2565b6000818152600860205260408120546001600160a01b031680610c4f5760405162461bcd60e51b8152602060048201526015602482015274546f6b656e20646f6573206e6f742065786973747360581b6044820152606401610953565b806012544210156112945760405162461bcd60e51b815260206004820152601160248201527014d85b19481b9bdd081b1a5d99481e595d607a1b6044820152606401610953565b60145442106112d35760405162461bcd60e51b815260206004820152600b60248201526a14d85b194818db1bdcd95960aa1b6044820152606401610953565b601e6011546112e29190612f46565b8160ff166112ef60035490565b6112f99190612f59565b11156113325760405162461bcd60e51b815260206004820152600860248201526714dbdb19081bdd5d60c21b6044820152606401610953565b8060ff166016546113439190612f6c565b34146113815760405162461bcd60e51b815260206004820152600d60248201526c496e636f72726563742066656560981b6044820152606401610953565b601554600160a01b900460ff16156113ab5760405162461bcd60e51b815260040161095390612f07565b60135442101561140e5760405162461bcd60e51b815260206004820152602860248201527f4f6e6c79206d696e747061737320686f6c6465727320616c6c6f77656420696e6044820152672070726573616c6560c01b6064820152608401610953565b6017546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015611447573d6000803e3d6000fd5b50610b4d83836120b2565b60006001600160a01b03821661147a5760405162461bcd60e51b81526004016109539061303e565b506001600160a01b03166000908152600a602052604090205490565b600e546001600160a01b031633146114c05760405162461bcd60e51b815260040161095390613011565b6001600160a01b03811660009081526010602052604090205460ff166115285760405162461bcd60e51b815260206004820152601b60248201527f446570757479204f776e657220646f6573206e6f7420657869747300000000006044820152606401610953565b6000805b600f5481101561158357826001600160a01b0316600f828154811061155357611553612ffb565b6000918252602090912001546001600160a01b031603611571578091505b8061157b81613075565b91505061152c565b50600f805461159490600190612f46565b815481106115a4576115a4612ffb565b600091825260209091200154600f80546001600160a01b0390921691839081106115d0576115d0612ffb565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600f805461160990600190612f46565b8154811061161957611619612ffb565b600091825260208083209190910180546001600160a01b03191690556001600160a01b038416808352601082526040808420805460ff191690558051918252918101929092527f3c3909677f69a0291b873bdd830b78dfb231df51c82872fde8d546da7cf85533910160405180910390a15050565b600e546001600160a01b031633146116b85760405162461bcd60e51b815260040161095390613011565b8063075bcd15146116fa5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c696420636f646560a01b6044820152606401610953565b600e80546001600160a01b031916905560408051338152600060208201527f4c19d31874b3f8325813d90efdd10758f703ab99b84367f07276ecd2cd69c95d91015b60405180910390a150565b600e546001600160a01b031633146117715760405162461bcd60e51b815260040161095390613011565b6001600160a01b0381166117b95760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610953565b600e80546001600160a01b0319166001600160a01b0383169081179091556040805133815260208101929092527f4c19d31874b3f8325813d90efdd10758f703ab99b84367f07276ecd2cd69c95d910161173c565b6000818152600c6020526040902080546060919061182b90612ecd565b905060000361186957600261183f8361211e565b600d60405160200161185393929190613101565b6040516020818303038152906040529050919050565b6002600c6000848152602001908152602001600020600d60405160200161185393929190613134565b600e546001600160a01b031633146118bc5760405162461bcd60e51b815260040161095390613011565b60165460408051918252602082018390527f92664190cca12aca9cd5309d87194bdda75bb51362d71c06e1a6f75c7c765711910160405180910390a1601655565b60606001805461089890612ecd565b6109258282612227565b600e546001600160a01b031633146119405760405162461bcd60e51b815260040161095390613011565b6001600160a01b03811660009081526010602052604090205460ff16156119a95760405162461bcd60e51b815260206004820152601b60248201527f446570757479204f776e657220616c72656164792065786973747300000000006044820152606401610953565b600f805460018082019092557f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020180546001600160a01b0319166001600160a01b038416908117909155600081815260106020908152604091829020805460ff19168517905581519283528201929092527f3c3909677f69a0291b873bdd830b78dfb231df51c82872fde8d546da7cf85533910161173c565b600e546001600160a01b03163314611a6c5760405162461bcd60e51b815260040161095390613011565b6019805460ff19166001179055565b601554600160a01b900460ff1615611aa55760405162461bcd60e51b815260040161095390612f07565b611ab184848484612046565b50505050565b600f8181548110611ac757600080fd5b6000918252602090912001546001600160a01b0316905081565b6000818152600860205260409020546060906001600160a01b0316611b3f5760405162461bcd60e51b8152602060048201526014602482015273105cdcd95d08191bd95cc81b9bdd08195e1a5cdd60621b6044820152606401610953565b60195460ff16611bdb5760028054611b5690612ecd565b80601f0160208091040260200160405190810160405280929190818152602001828054611b8290612ecd565b8015611bcf5780601f10611ba457610100808354040283529160200191611bcf565b820191906000526020600020905b815481529060010190602001808311611bb257829003601f168201915b50505050509050919050565b610c4f8261180e565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250905060008185604051602001611c3492919061315b565b604051602081830303815290604052805190602001209050600060018286604001518760000151886020015160405160008152602001604052604051611c96949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611cb8573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60028054610b5f90612ecd565b600e546001600160a01b03163314611d045760405162461bcd60e51b815260040161095390613011565b60158054821515600160a01b0260ff60a01b199091161790556040517f0e2fb031ee032dc02d8011dc50b816eb450cf856abd8261680dac74f72165bd29061173c90831515815260200190565b6001600160a01b039182166000908152600b6020908152604080832093909416825291909152205460ff1690565b600e546001600160a01b0316331480611da757503360009081526010602052604090205460ff165b611df35760405162461bcd60e51b815260206004820152601d60248201527f43616c6c6572206973206e6f74206f776e6572206f72206465707574790000006044820152606401610953565b601e8151601854611e049190612f59565b1115611e525760405162461bcd60e51b815260206004820152601a60248201527f4d617820726573657276656420746f6b656e73206d696e7465640000000000006044820152606401610953565b805160188054909101905560005b81518160ff16101561092557611ea5828260ff1681518110611e8457611e84612ffb565b6020026020010151611e9560035490565b611ea0906001612f59565b6122e5565b80611eaf8161317d565b915050611e60565b6000611ec2826111f0565b9050806001600160a01b0316836001600160a01b031603611f1f5760405162461bcd60e51b815260206004820152601760248201527621b0b7103737ba1030b8383937bb32903a379039b2b63360491b6044820152606401610953565b336001600160a01b0382161480611f3b5750611f3b8133611d51565b611f875760405162461bcd60e51b815260206004820152601f60248201527f4e6f7420616c6c6f77656420746f2075706461746520617070726f76616c73006044820152606401610953565b60008281526009602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b611fed83826122ef565b6120095760405162461bcd60e51b81526004016109539061319c565b610b4d838383612346565b8061201f33826122ef565b61203b5760405162461bcd60e51b81526004016109539061319c565b611ab1848484612346565b612051848484612014565b61205d848484846123d0565b611ab15760405162461bcd60e51b815260206004820152601460248201527314d8599948151c985b9cd9995c8819985a5b195960621b6044820152606401610953565b610cd86120ac826111f0565b82612484565b60005b8160ff168160ff161015610b4d576120d083611e9560035490565b806120da8161317d565b9150506120b5565b60026120ee8282613214565b507fe6e4cd5c2dc7d2c20519b41832cd550fd3ea1186bf299d108179bf71fb8e00e58160405161173c91906129fa565b6060816000036121455750506040805180820190915260018152600360fc1b602082015290565b8160005b811561216f578061215981613075565b91506121689050600a836132ea565b9150612149565b60008167ffffffffffffffff81111561218a5761218a612a84565b6040519080825280601f01601f1916602001820160405280156121b4576020820181803683370190505b5090505b841561221f576121c9600183612f46565b91506121d6600a866132fe565b6121e1906030612f59565b60f81b8183815181106121f6576121f6612ffb565b60200101906001600160f81b031916908160001a905350612218600a866132ea565b94506121b8565b949350505050565b336001600160a01b038316036122795760405162461bcd60e51b815260206004820152601760248201527621b0b7103737ba1030b8383937bb32903a379039b2b63360491b6044820152606401610953565b336000818152600b602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610925828261251e565b6000806122fb836111f0565b9050806001600160a01b0316846001600160a01b0316148061233657506000838152600960205260409020546001600160a01b038581169116145b8061221f575061221f8185611d51565b6001600160a01b03821661236c5760405162461bcd60e51b81526004016109539061303e565b6123768382612628565b612380838261270f565b61238a82826127f2565b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60006123e4846001600160a01b0316612888565b6123f05750600161221f565b60405163785cf2dd60e11b81526000906001600160a01b0386169063f0b9e5ba9061242390899088908890600401613312565b6020604051808303816000875af1158015612442573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124669190613339565b6001600160e01b03191663785cf2dd60e11b14915050949350505050565b8061248f33826122ef565b6124ab5760405162461bcd60e51b81526004016109539061319c565b6124b58383612628565b6124bf838361270f565b6124c8826128c1565b60008281526008602052604080822080546001600160a01b0319169055518391906001600160a01b038616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a4505050565b6001600160a01b0382166125445760405162461bcd60e51b81526004016109539061303e565b6000818152600860205260409020546001600160a01b0316156125a05760405162461bcd60e51b8152602060048201526014602482015273417373657420616c72656164792065786973747360601b6044820152606401610953565b6125aa82826127f2565b600380546000838152600760205260408082208390556001830184559281527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b909101839055905182916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b816001600160a01b031661263b826111f0565b6001600160a01b03161461269d5760405162461bcd60e51b8152602060048201526024808201527f417373657420646f6573206e6f742062656c6f6e6720746f20676976656e206f6044820152633bb6b2b960e11b6064820152608401610953565b6000818152600960205260409020546001600160a01b0316156109255760008181526009602052604080822080546001600160a01b0319169055518291906001600160a01b038516907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908390a45050565b6001600160a01b0382166000908152600a602052604081205461273490600190612f46565b600083815260066020526040902054909150808214612787576001600160a01b03841660009081526005602090815260408083208584528252808320548484528184208190558352600690915290208190555b60008381526006602090815260408083208390556001600160a01b0387168084526005835281842086855283528184208490558352600a9091529020546127d090600190612f46565b6001600160a01b039094166000908152600a6020526040902093909355505050565b60006127fd83611452565b6001600160a01b0384166000818152600560209081526040808320858452825280832087905586835260068252808320859055928252600a90522054909150612847906001612f59565b6001600160a01b039093166000818152600a602090815260408083209690965593815260089093529290912080546001600160a01b03191690921790915550565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061221f575050151592915050565b6003546000906128d390600190612f46565b600083815260076020526040812054600380549394509092849081106128fb576128fb612ffb565b90600052602060002001549050806003838154811061291c5761291c612ffb565b600091825260208083209091019290925582815260079091526040808220849055858252812055600380548061295457612954613356565b6001900381819060005260206000200160009055905550505050565b6001600160e01b031981168114610cd857600080fd5b60006020828403121561299857600080fd5b81356129a381612970565b9392505050565b60005b838110156129c55781810151838201526020016129ad565b50506000910152565b600081518084526129e68160208601602086016129aa565b601f01601f19169290920160200192915050565b6020815260006129a360208301846129ce565b600060208284031215612a1f57600080fd5b5035919050565b6001600160a01b0381168114610cd857600080fd5b60008060408385031215612a4e57600080fd5b8235612a5981612a26565b946020939093013593505050565b600060208284031215612a7957600080fd5b81356129a381612a26565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612ac357612ac3612a84565b604052919050565b60ff81168114610cd857600080fd5b600060608284031215612aec57600080fd5b6040516060810181811067ffffffffffffffff82111715612b0f57612b0f612a84565b806040525080915082358152602083013560208201526040830135612b3381612acb565b6040919091015292915050565b600080600080600060e08688031215612b5857600080fd5b8535612b6381612a26565b94506020860135612b7381612a26565b93506040860135925060608601359150612b908760808801612ada565b90509295509295909350565b600080600060608486031215612bb157600080fd5b8335612bbc81612a26565b92506020840135612bcc81612a26565b929592945050506040919091013590565b600080600060608486031215612bf257600080fd5b8335612bfd81612a26565b92506020840135612bcc81612acb565b600067ffffffffffffffff831115612c2757612c27612a84565b612c3a601f8401601f1916602001612a9a565b9050828152838383011115612c4e57600080fd5b828260208301376000602084830101529392505050565b600060208284031215612c7757600080fd5b813567ffffffffffffffff811115612c8e57600080fd5b8201601f81018413612c9f57600080fd5b61221f84823560208401612c0d565b60008060408385031215612cc157600080fd5b8235612ccc81612a26565b91506020830135612cdc81612acb565b809150509250929050565b8015158114610cd857600080fd5b60008060408385031215612d0857600080fd5b8235612d1381612a26565b91506020830135612cdc81612ce7565b60008060008060808587031215612d3957600080fd5b8435612d4481612a26565b93506020850135612d5481612a26565b925060408501359150606085013567ffffffffffffffff811115612d7757600080fd5b8501601f81018713612d8857600080fd5b612d9787823560208401612c0d565b91505092959194509250565b60008060808385031215612db657600080fd5b82359150612dc78460208501612ada565b90509250929050565b600060208284031215612de257600080fd5b81356129a381612ce7565b60008060408385031215612e0057600080fd5b8235612e0b81612a26565b91506020830135612cdc81612a26565b60006020808385031215612e2e57600080fd5b823567ffffffffffffffff80821115612e4657600080fd5b818501915085601f830112612e5a57600080fd5b813581811115612e6c57612e6c612a84565b8060051b9150612e7d848301612a9a565b8181529183018401918481019088841115612e9757600080fd5b938501935b83851015612ec15784359250612eb183612a26565b8282529385019390850190612e9c565b98975050505050505050565b600181811c90821680612ee157607f821691505b602082108103612f0157634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600f908201526e10dbdb9d1c9858dd081c185d5cd959608a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c4f57610c4f612f30565b80820180821115610c4f57610c4f612f30565b6000816000190483118215151615612f8657612f86612f30565b500290565b600060208284031215612f9d57600080fd5b81516129a381612ce7565b600060208284031215612fba57600080fd5b81516129a381612a26565b600060208284031215612fd757600080fd5b81516129a381612acb565b60ff8181168382160190811115610c4f57610c4f612f30565b634e487b7160e01b600052603260045260246000fd5b60208082526013908201527221b0b63632b91034b9903737ba1037bbb732b960691b604082015260600190565b60208082526018908201527f5a65726f2061646472657373206e6f7420616c6c6f7765640000000000000000604082015260600190565b60006001820161308757613087612f30565b5060010190565b6000815461309b81612ecd565b600182811680156130b357600181146130c8576130f7565b60ff19841687528215158302870194506130f7565b8560005260208060002060005b858110156130ee5781548a8201529084019082016130d5565b50505082870194505b5050505092915050565b600061310d828661308e565b845161311d8183602089016129aa565b6131298183018661308e565b979650505050505050565b600061315261314c613146848861308e565b8661308e565b8461308e565b95945050505050565b6000835161316d8184602088016129aa565b9190910191825250602001919050565b600060ff821660ff810361319357613193612f30565b60010192915050565b60208082526010908201526f21b0b7103737ba103a3930b739b332b960811b604082015260600190565b601f821115610b4d57600081815260208120601f850160051c810160208610156131ed5750805b601f850160051c820191505b8181101561320c578281556001016131f9565b505050505050565b815167ffffffffffffffff81111561322e5761322e612a84565b6132428161323c8454612ecd565b846131c6565b602080601f831160018114613277576000841561325f5750858301515b600019600386901b1c1916600185901b17855561320c565b600085815260208120601f198616915b828110156132a657888601518255948401946001909101908401613287565b50858210156132c45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601260045260246000fd5b6000826132f9576132f96132d4565b500490565b60008261330d5761330d6132d4565b500690565b60018060a01b038416815282602082015260606040820152600061315260608301846129ce565b60006020828403121561334b57600080fd5b81516129a381612970565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220c98077b88d5b3c8a87e109dd5ec09e586b9eee9ad7d157be620b998fe081454164736f6c63430008100033

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

000000000000000000000000e65f378d11ba8ea0a1cc5223abc555fa1bbbe2ea000000000000000000000000000000000000000000000000000000006335a4e0000000000000000000000000000000000000000000000000000000006336f660000000000000000000000000347afa0934ac1b62cab4d68542aa130a6e802ca3000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d4e6f317257527856627750347a62717671704771763541677339713655325267624c7655616d3641546845380000000000000000000000

-----Decoded View---------------
Arg [0] : _mintPassContract (address): 0xE65f378d11BA8eA0A1cC5223aBC555Fa1Bbbe2EA
Arg [1] : _preSaleStarts (uint256): 1664460000
Arg [2] : _preSaleEnds (uint256): 1664546400
Arg [3] : _coldWallet (address): 0x347AFA0934ac1B62CAb4d68542aa130A6E802Ca3
Arg [4] : _price (uint256): 100000000000000000
Arg [5] : _baseurl (string): ipfs://QmNo1rWRxVbwP4zbqvqpGqv5Ags9q6U2RgbLvUam6AThE8

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 000000000000000000000000e65f378d11ba8ea0a1cc5223abc555fa1bbbe2ea
Arg [1] : 000000000000000000000000000000000000000000000000000000006335a4e0
Arg [2] : 000000000000000000000000000000000000000000000000000000006336f660
Arg [3] : 000000000000000000000000347afa0934ac1b62cab4d68542aa130a6e802ca3
Arg [4] : 000000000000000000000000000000000000000000000000016345785d8a0000
Arg [5] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000035
Arg [7] : 697066733a2f2f516d4e6f317257527856627750347a62717671704771763541
Arg [8] : 677339713655325267624c7655616d3641546845380000000000000000000000


Deployed Bytecode Sourcemap

654:6373:8:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18115:168:1;;;;;;;;;;-1:-1:-1;18115:168:1;;;;;:::i;:::-;-1:-1:-1;;;;;;18242:33:1;18213:4;18242:33;;;:19;:33;;;;;;;;;18115:168;;;;565:14:9;;558:22;540:41;;528:2;513:18;18115:168:1;;;;;;;;3146:85;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;6177:119::-;;;;;;;;;;-1:-1:-1;6177:119:1;;;;;:::i;:::-;6237:7;6264:24;;;:14;:24;;;;;;-1:-1:-1;;;;;6264:24:1;;6177:119;;;;-1:-1:-1;;;;;1697:32:9;;;1679:51;;1667:2;1652:18;6177:119:1;1533:203:9;662:103:2;;;;;;;;;;-1:-1:-1;662:103:2;;;;;:::i;:::-;;:::i;:::-;;153:45:6;;;;;;;;;;-1:-1:-1;153:45:6;;;;;:::i;:::-;;;;;;;;;;;;;;;;17496:95:1;;;;;;;;;;-1:-1:-1;17567:9:1;:16;17496:95;;;2595:25:9;;;2583:2;2568:18;17496:95:1;2449:177:9;5002:830:8;;;;;;;;;;-1:-1:-1;5002:830:8;;;;;:::i;:::-;;:::i;4247:188::-;;;;;;;;;;-1:-1:-1;4247:188:8;;;;;:::i;:::-;;:::i;221:23:2:-;;;;;;;;;;;;;:::i;17099:239:1:-;;;;;;;;;;-1:-1:-1;17099:239:1;;;;;:::i;:::-;;:::i;1049:28:8:-;;;;;;;;;;;;;;;;4443:202;;;;;;;;;;-1:-1:-1;4443:202:8;;;;;:::i;:::-;;:::i;4893:97::-;;;;;;;;;;-1:-1:-1;4893:97:8;;;;;:::i;:::-;;:::i;2879:657::-;;;;;;:::i;:::-;;:::i;4937:153:1:-;;;;;;;;;;-1:-1:-1;4937:153:1;;;;;:::i;:::-;4992:4;5025:20;;;:10;:20;;;;;;-1:-1:-1;;;;;5025:20:1;5063:19;;;4937:153;17937:170;;;;;;;;;;-1:-1:-1;17937:170:1;;;;;:::i;:::-;;:::i;1084:22:8:-;;;;;;;;;;-1:-1:-1;1084:22:8;;;;;;;;826:23;;;;;;;;;;;;;;;;5840:133;;;;;;;;;;-1:-1:-1;5840:133:8;;;;;:::i;:::-;;:::i;4533:207:1:-;;;;;;;;;;-1:-1:-1;4533:207:1;;;;;:::i;:::-;;:::i;2604:267:8:-;;;;;;:::i;:::-;;:::i;1009:33::-;;;;;;;;;;-1:-1:-1;1009:33:8;;;;-1:-1:-1;;;;;1009:33:8;;;4118:183:1;;;;;;;;;;-1:-1:-1;4118:183:1;;;;;:::i;:::-;;:::i;1988:587:6:-;;;;;;;;;;-1:-1:-1;1988:587:6;;;;;:::i;:::-;;:::i;2821:221::-;;;;;;;;;;-1:-1:-1;2821:221:6;;;;;:::i;:::-;;:::i;972:208::-;;;;;;;;;;-1:-1:-1;972:208:6;;;;;:::i;:::-;;:::i;1278:66:8:-;;;;;;;;;;-1:-1:-1;1278:66:8;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;2106:376:2;;;;;;;;;;-1:-1:-1;2106:376:2;;;;;:::i;:::-;;:::i;3922:129:8:-;;;;;;;;;;-1:-1:-1;3922:129:8;;;;;:::i;:::-;;:::i;88:20:6:-;;;;;;;;;;-1:-1:-1;88:20:6;;;;-1:-1:-1;;;;;88:20:6;;;3345:89:1;;;;;;;;;;;;;:::i;982:20:8:-;;;;;;;;;;;;;;;;773:122:2;;;;;;;;;;-1:-1:-1;773:122:2;;;;;:::i;:::-;;:::i;1469:261:6:-;;;;;;;;;;-1:-1:-1;1469:261:6;;;;;:::i;:::-;;:::i;6116:71:8:-;;;;;;;;;;;;;:::i;889:28::-;;;;;;;;;;-1:-1:-1;889:28:8;;;;-1:-1:-1;;;889:28:8;;;;;;758;;;;;;;;;;;;;;;;4653:232;;;;;;;;;;-1:-1:-1;4653:232:8;;;;;:::i;:::-;;:::i;115:29:6:-;;;;;;;;;;-1:-1:-1;115:29:6;;;;;:::i;:::-;;:::i;6195:279:8:-;;;;;;;;;;-1:-1:-1;6195:279:8;;;;;:::i;:::-;;:::i;6482:369::-;;;;;;;;;;-1:-1:-1;6482:369:8;;;;;:::i;:::-;;:::i;745:26:1:-;;;;;;;;;;;;;:::i;706:24:8:-;;;;;;;;;;;;;;;;5981:127;;;;;;;;;;-1:-1:-1;5981:127:8;;;;;:::i;:::-;;:::i;7182:182:1:-;;;;;;;;;;-1:-1:-1;7182:182:1;;;;;:::i;:::-;;:::i;3544:368:8:-;;;;;;;;;;-1:-1:-1;3544:368:8;;;;;:::i;:::-;;:::i;793:26::-;;;;;;;;;;;;;;;;3146:85:1;3185:13;3218:5;3211:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3146:85;:::o;662:103:2:-;728:29;743:3;748:8;728:14;:29::i;:::-;662:103;;:::o;5002:830:8:-;1586:8;;-1:-1:-1;;;1586:8:8;;;;1585:9;1577:37;;;;-1:-1:-1;;;1577:37:8;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;;;;5189:24:8;::::1;;::::0;;;:17:::1;:24;::::0;;;;;;;:37;;;;;;;;;::::1;;5188:38;5166:116;;;::::0;-1:-1:-1;;;5166:116:8;;11038:2:9;5166:116:8::1;::::0;::::1;11020:21:9::0;11077:2;11057:18;;;11050:30;11116;11096:18;;;11089:58;11164:18;;5166:116:8::1;10836:352:9::0;5166:116:8::1;5295:12;5376:21;5425:4;5449:11:::0;6975:9;5334:245:::1;::::0;-1:-1:-1;;;;;;11500:33:9;;;5334:245:8::1;::::0;::::1;11488:46:9::0;-1:-1:-1;;11621:2:9;11617:15;;;11613:24;;11600:11;;;11593:45;11654:12;;;11647:28;;;;11691:12;;;11684:28;11746:15;;;11742:24;;11728:12;;;11721:46;11802:15;;;;11798:24;11783:13;;;11776:47;11839:13;;;11832:29;;;11877:13;;5334:245:8::1;;;;;;;;;;;;5310:280;;;;;;5295:295;;5601:14;5618:26;5628:4;5634:9;5618;:26::i;:::-;5601:43;;5673:5;-1:-1:-1::0;;;;;5663:15:8::1;:6;-1:-1:-1::0;;;;;5663:15:8::1;;5655:56;;;::::0;-1:-1:-1;;;5655:56:8;;12103:2:9;5655:56:8::1;::::0;::::1;12085:21:9::0;12142:2;12122:18;;;12115:30;12181;12161:18;;;12154:58;12229:18;;5655:56:8::1;11901:352:9::0;5655:56:8::1;-1:-1:-1::0;;;;;5722:25:8;::::1;;::::0;;;:17:::1;:25;::::0;;;;;;;:38;;;;;;;;:45;;-1:-1:-1;;5722:45:8::1;5763:4;5722:45;::::0;;5778:46:::1;5740:6:::0;5810:3;5815:8;5778:23:::1;:46::i;:::-;5155:677;;5002:830:::0;;;;;:::o;4247:188::-;1586:8;;-1:-1:-1;;;1586:8:8;;;;1585:9;1577:37;;;;-1:-1:-1;;;1577:37:8;;;;;;;:::i;:::-;4386:41:::1;4406:5;4413:3;4418:8;4386:19;:41::i;:::-;4247:188:::0;;;:::o;221:23:2:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;17099:239:1:-;17208:7;17250:17;17260:6;17250:9;:17::i;:::-;17241:6;:26;17233:52;;;;-1:-1:-1;;;17233:52:1;;12460:2:9;17233:52:1;;;12442:21:9;12499:2;12479:18;;;12472:30;-1:-1:-1;;;12518:18:9;;;12511:43;12571:18;;17233:52:1;12258:337:9;17233:52:1;-1:-1:-1;;;;;;17303:19:1;;;;;;:11;:19;;;;;;;;:27;;;;;;;;;17099:239;;;;;:::o;4443:202:8:-;1586:8;;-1:-1:-1;;;1586:8:8;;;;1585:9;1577:37;;;;-1:-1:-1;;;1577:37:8;;;;;;;:::i;:::-;4586:51:::1;4610:5;4617:3;4622:8;4586:51;;;;;;;;;;;;;-1:-1:-1::0;;;4586:51:8::1;;::::0;:23:::1;:51::i;4893:97::-:0;1586:8;;-1:-1:-1;;;1586:8:8;;;;1585:9;1577:37;;;;-1:-1:-1;;;1577:37:8;;;;;;;:::i;:::-;4962:20:::1;4973:8;4962:10;:20::i;:::-;4893:97:::0;:::o;2879:657::-;2974:8;1719:13;;1700:15;:32;;1692:63;;;;-1:-1:-1;;;1692:63:8;;12802:2:9;1692:63:8;;;12784:21:9;12841:2;12821:18;;;12814:30;-1:-1:-1;;;12860:18:9;;;12853:47;12917:18;;1692:63:8;12600:341:9;1692:63:8;1792:8;;1774:15;:26;1766:50;;;;-1:-1:-1;;;1766:50:8;;13148:2:9;1766:50:8;;;13130:21:9;13187:2;13167:18;;;13160:30;-1:-1:-1;;;13206:18:9;;;13199:41;13257:18;;1766:50:8;12946:335:9;1766:50:8;1158:2;1863:9;;:27;;;;:::i;:::-;1851:8;1835:24;;:13;17567:9:1;:16;;17496:95;1835:13:8;:24;;;;:::i;:::-;:55;;1827:76;;;;-1:-1:-1;;;1827:76:8;;13883:2:9;1827:76:8;;;13865:21:9;13922:1;13902:18;;;13895:29;-1:-1:-1;;;13940:18:9;;;13933:38;13988:18;;1827:76:8;13681:331:9;1827:76:8;1941:8;1935:14;;:5;;:14;;;;:::i;:::-;1922:9;:27;1914:53;;;;-1:-1:-1;;;1914:53:8;;14392:2:9;1914:53:8;;;14374:21:9;14431:2;14411:18;;;14404:30;-1:-1:-1;;;14450:18:9;;;14443:43;14503:18;;1914:53:8;14190:337:9;1914:53:8;3021:11:::1;;3003:15;:29;2995:56;;;::::0;-1:-1:-1;;;2995:56:8;;14734:2:9;2995:56:8::1;::::0;::::1;14716:21:9::0;14773:2;14753:18;;;14746:30;-1:-1:-1;;;14792:18:9;;;14785:44;14846:18;;2995:56:8::1;14532:338:9::0;2995:56:8::1;3070:8;::::0;:27:::1;::::0;-1:-1:-1;;;3070:27:8;;::::1;::::0;::::1;2595:25:9::0;;;-1:-1:-1;;;;;3070:8:8;;::::1;::::0;:15:::1;::::0;2568:18:9;;3070:27:8::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3062:57;;;::::0;-1:-1:-1;;;3062:57:8;;15327:2:9;3062:57:8::1;::::0;::::1;15309:21:9::0;15366:2;15346:18;;;15339:30;-1:-1:-1;;;15385:18:9;;;15378:47;15442:18;;3062:57:8::1;15125:341:9::0;3062:57:8::1;3138:8;::::0;:28:::1;::::0;-1:-1:-1;;;3138:28:8;;::::1;::::0;::::1;2595:25:9::0;;;3170:10:8::1;::::0;-1:-1:-1;;;;;3138:8:8::1;::::0;:16:::1;::::0;2568:18:9;;3138:28:8::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;3138:42:8::1;;3130:90;;;::::0;-1:-1:-1;;;3130:90:8;;15929:2:9;3130:90:8::1;::::0;::::1;15911:21:9::0;15968:2;15948:18;;;15941:30;16007:34;15987:18;;;15980:62;-1:-1:-1;;;16058:18:9;;;16051:33;16101:19;;3130:90:8::1;15727:399:9::0;3130:90:8::1;3231:10;::::0;:30:::1;::::0;-1:-1:-1;;;;;3231:10:8;;::::1;::::0;3251:9:::1;3231:30:::0;::::1;;;::::0;:10:::1;:30:::0;:10;:30;3251:9;3231:10;:30;::::1;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;3294:8:8::1;::::0;:37:::1;::::0;-1:-1:-1;;;3294:37:8;;::::1;::::0;::::1;2595:25:9::0;;;3272:19:8::1;::::0;-1:-1:-1;;;;;3294:8:8::1;::::0;:25:::1;::::0;2568:18:9;;3294:37:8::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3272:59:::0;-1:-1:-1;1210:1:8::1;3350:22;3364:8:::0;3272:59;3350:22:::1;:::i;:::-;:43;;;;3342:74;;;::::0;-1:-1:-1;;;3342:74:8;;16738:2:9;3342:74:8::1;::::0;::::1;16720:21:9::0;16777:2;16757:18;;;16750:30;-1:-1:-1;;;16796:18:9;;;16789:48;16854:18;;3342:74:8::1;16536:342:9::0;3342:74:8::1;3427:8;::::0;-1:-1:-1;;;;;3427:8:8::1;:28;3456:10:::0;3468:22:::1;3482:8:::0;3468:13;:22:::1;:::i;:::-;3427:64;::::0;-1:-1:-1;;;;;;3427:64:8::1;::::0;;;;;;::::1;::::0;::::1;17053:25:9::0;;;;17126:4;17114:17;17094:18;;;17087:45;17026:18;;3427:64:8::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;3502:26;3513:4;3519:8;3502:10;:26::i;:::-;2984:552;2879:657:::0;;;;:::o;17937:170:1:-;17996:7;18033:13;17567:9;:16;;17496:95;18033:13;18024:6;:22;18016:48;;;;-1:-1:-1;;;18016:48:1;;12460:2:9;18016:48:1;;;12442:21:9;12499:2;12479:18;;;12472:30;-1:-1:-1;;;12518:18:9;;;12511:43;12571:18;;18016:48:1;12258:337:9;18016:48:1;18082:9;18092:6;18082:17;;;;;;;;:::i;:::-;;;;;;;;;18075:24;;17937:170;;;:::o;5840:133:8:-;483:5:6;;-1:-1:-1;;;;;483:5:6;469:10;:19;461:51;;;;-1:-1:-1;;;461:51:6;;;;;;;:::i;:::-;5925:40:8::1;5951:13;5925:25;:40::i;4533:207:1:-:0;4589:7;4625:20;;;:10;:20;;;;;;-1:-1:-1;;;;;4625:20:1;;4656:53;;;;-1:-1:-1;;;4656:53:1;;17825:2:9;4656:53:1;;;17807:21:9;17864:2;17844:18;;;17837:30;-1:-1:-1;;;17883:18:9;;;17876:51;17944:18;;4656:53:1;17623:345:9;2604:267:8;2671:8;1719:13;;1700:15;:32;;1692:63;;;;-1:-1:-1;;;1692:63:8;;12802:2:9;1692:63:8;;;12784:21:9;12841:2;12821:18;;;12814:30;-1:-1:-1;;;12860:18:9;;;12853:47;12917:18;;1692:63:8;12600:341:9;1692:63:8;1792:8;;1774:15;:26;1766:50;;;;-1:-1:-1;;;1766:50:8;;13148:2:9;1766:50:8;;;13130:21:9;13187:2;13167:18;;;13160:30;-1:-1:-1;;;13206:18:9;;;13199:41;13257:18;;1766:50:8;12946:335:9;1766:50:8;1158:2;1863:9;;:27;;;;:::i;:::-;1851:8;1835:24;;:13;17567:9:1;:16;;17496:95;1835:13:8;:24;;;;:::i;:::-;:55;;1827:76;;;;-1:-1:-1;;;1827:76:8;;13883:2:9;1827:76:8;;;13865:21:9;13922:1;13902:18;;;13895:29;-1:-1:-1;;;13940:18:9;;;13933:38;13988:18;;1827:76:8;13681:331:9;1827:76:8;1941:8;1935:14;;:5;;:14;;;;:::i;:::-;1922:9;:27;1914:53;;;;-1:-1:-1;;;1914:53:8;;14392:2:9;1914:53:8;;;14374:21:9;14431:2;14411:18;;;14404:30;-1:-1:-1;;;14450:18:9;;;14443:43;14503:18;;1914:53:8;14190:337:9;1914:53:8;1586:8:::1;::::0;-1:-1:-1;;;1586:8:8;::::1;;;1585:9;1577:37;;;;-1:-1:-1::0;;;1577:37:8::1;;;;;;;:::i;:::-;2729:11:::2;;2710:15;:30;;2702:83;;;::::0;-1:-1:-1;;;2702:83:8;;18175:2:9;2702:83:8::2;::::0;::::2;18157:21:9::0;18214:2;18194:18;;;18187:30;18253:34;18233:18;;;18226:62;-1:-1:-1;;;18304:18:9;;;18297:38;18352:19;;2702:83:8::2;17973:404:9::0;2702:83:8::2;2796:10;::::0;:30:::2;::::0;-1:-1:-1;;;;;2796:10:8;;::::2;::::0;2816:9:::2;2796:30:::0;::::2;;;::::0;:10:::2;:30:::0;:10;:30;2816:9;2796:10;:30;::::2;;;;;;;;;;;;;::::0;::::2;;;;;;2837:26;2848:4;2854:8;2837:10;:26::i;4118:183:1:-:0;4174:7;-1:-1:-1;;;;;4202:20:1;;4194:57;;;;-1:-1:-1;;;4194:57:1;;;;;;;:::i;:::-;-1:-1:-1;;;;;;4269:24:1;;;;;:16;:24;;;;;;;4118:183::o;1988:587:6:-;483:5;;-1:-1:-1;;;;;483:5:6;469:10;:19;461:51;;;;-1:-1:-1;;;461:51:6;;;;;;;:::i;:::-;-1:-1:-1;;;;;2072:26:6;::::1;;::::0;;;:13:::1;:26;::::0;;;;;::::1;;2064:66;;;::::0;-1:-1:-1;;;2064:66:6;;18937:2:9;2064:66:6::1;::::0;::::1;18919:21:9::0;18976:2;18956:18;;;18949:30;19015:29;18995:18;;;18988:57;19062:18;;2064:66:6::1;18735:351:9::0;2064:66:6::1;2141:18;::::0;2170:127:::1;2194:12;:19:::0;2190:23;::::1;2170:127;;;2258:11;-1:-1:-1::0;;;;;2239:30:6::1;:12;2252:1;2239:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;-1:-1:-1;;;;;2239:15:6::1;:30:::0;2235:50:::1;;2284:1;2271:14;;2235:50;2215:3:::0;::::1;::::0;::::1;:::i;:::-;;;;2170:127;;;-1:-1:-1::0;2376:12:6::1;2389:19:::0;;:23:::1;::::0;2411:1:::1;::::0;2389:23:::1;:::i;:::-;2376:37;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;2349:12:::1;:24:::0;;-1:-1:-1;;;;;2376:37:6;;::::1;::::0;2362:10;;2349:24;::::1;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;:64:::0;;-1:-1:-1;;;;;;2349:64:6::1;-1:-1:-1::0;;;;;2349:64:6;;;::::1;::::0;;;::::1;::::0;;2431:12:::1;2444:19:::0;;:23:::1;::::0;-1:-1:-1;;2444:23:6::1;:::i;:::-;2431:37;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;;;::::1;2424:44:::0;;-1:-1:-1;;;;;;2424:44:6::1;::::0;;-1:-1:-1;;;;;2479:26:6;::::1;::::0;;;:13:::1;:26:::0;;;;;;:34;;-1:-1:-1;;2479:34:6::1;::::0;;2529:38;;19399:51:9;;;19466:18;;;19459:50;;;;2529:38:6::1;::::0;19372:18:9;2529:38:6::1;;;;;;;2053:522;1988:587:::0;:::o;2821:221::-;483:5;;-1:-1:-1;;;;;483:5:6;469:10;:19;461:51;;;;-1:-1:-1;;;461:51:6;;;;;;;:::i;:::-;2909:15:::1;2928:9;2909:28;2901:53;;;::::0;-1:-1:-1;;;2901:53:6;;19722:2:9;2901:53:6::1;::::0;::::1;19704:21:9::0;19761:2;19741:18;;;19734:30;-1:-1:-1;;;19780:18:9;;;19773:42;19832:18;;2901:53:6::1;19520:336:9::0;2901:53:6::1;2965:5;:18:::0;;-1:-1:-1;;;;;;2965:18:6::1;::::0;;2999:35:::1;::::0;;3016:10:::1;20073:34:9::0;;-1:-1:-1;20138:2:9;20123:18;;20116:43;2999:35:6::1;::::0;20008:18:9;2999:35:6::1;;;;;;;;2821:221:::0;:::o;972:208::-;483:5;;-1:-1:-1;;;;;483:5:6;469:10;:19;461:51;;;;-1:-1:-1;;;461:51:6;;;;;;;:::i;:::-;-1:-1:-1;;;;;1048:25:6;::::1;1040:53;;;::::0;-1:-1:-1;;;1040:53:6;;20372:2:9;1040:53:6::1;::::0;::::1;20354:21:9::0;20411:2;20391:18;;;20384:30;-1:-1:-1;;;20430:18:9;;;20423:45;20485:18;;1040:53:6::1;20170:339:9::0;1040:53:6::1;1104:5;:17:::0;;-1:-1:-1;;;;;;1104:17:6::1;-1:-1:-1::0;;;;;1104:17:6;::::1;::::0;;::::1;::::0;;;1137:35:::1;::::0;;1154:10:::1;20073:34:9::0;;20138:2;20123:18;;20116:43;;;;1137:35:6::1;::::0;20008:18:9;1137:35:6::1;19861:304:9::0;2106:376:2;2249:19;;;;:9;:19;;;;;2243:33;;2208:13;;2249:19;2243:33;;;:::i;:::-;;;2280:1;2243:38;2239:148;;2329:12;2343:19;:8;:17;:19::i;:::-;2364:9;2312:62;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2298:77;;2106:376;;;:::o;2239:148::-;2428:12;2442:9;:19;2452:8;2442:19;;;;;;;;;;;2463:9;2411:62;;;;;;;;;;:::i;3922:129:8:-;483:5:6;;-1:-1:-1;;;;;483:5:6;469:10;:19;461:51;;;;-1:-1:-1;;;461:51:6;;;;;;;:::i;:::-;4004:5:8::1;::::0;3992:26:::1;::::0;;22377:25:9;;;22433:2;22418:18;;22411:34;;;3992:26:8::1;::::0;22350:18:9;3992:26:8::1;;;;;;;4029:5;:14:::0;3922:129::o;3345:89:1:-;3386:13;3419:7;3412:14;;;;;:::i;773:122:2:-;847:40;872:3;877:9;847:24;:40::i;1469:261:6:-;483:5;;-1:-1:-1;;;;;483:5:6;469:10;:19;461:51;;;;-1:-1:-1;;;461:51:6;;;;;;;:::i;:::-;-1:-1:-1;;;;;1546:21:6;::::1;;::::0;;;:13:::1;:21;::::0;;;;;::::1;;1545:22;1537:62;;;::::0;-1:-1:-1;;;1537:62:6;;22658:2:9;1537:62:6::1;::::0;::::1;22640:21:9::0;22697:2;22677:18;;;22670:30;22736:29;22716:18;;;22709:57;22783:18;;1537:62:6::1;22456:351:9::0;1537:62:6::1;1610:12;:25:::0;;::::1;::::0;;::::1;::::0;;;;::::1;::::0;;-1:-1:-1;;;;;;1610:25:6::1;-1:-1:-1::0;;;;;1610:25:6;::::1;::::0;;::::1;::::0;;;-1:-1:-1;1646:21:6;;;:13:::1;1610:25;1646:21:::0;;;;;;;;:28;;-1:-1:-1;;1646:28:6::1;::::0;::::1;::::0;;1690:32;;19399:51:9;;;19466:18;;19459:50;;;;1690:32:6::1;::::0;19372:18:9;1690:32:6::1;19231:284:9::0;6116:71:8;483:5:6;;-1:-1:-1;;;;;483:5:6;469:10;:19;461:51;;;;-1:-1:-1;;;461:51:6;;;;;;;:::i;:::-;6162:10:8::1;:17:::0;;-1:-1:-1;;6162:17:8::1;6175:4;6162:17;::::0;;6116:71::o;4653:232::-;1586:8;;-1:-1:-1;;;1586:8:8;;;;1585:9;1577:37;;;;-1:-1:-1;;;1577:37:8;;;;;;;:::i;:::-;4825:52:::1;4849:5;4856:3;4861:8;4871:5;4825:23;:52::i;:::-;4653:232:::0;;;;:::o;115:29:6:-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;115:29:6;;-1:-1:-1;115:29:6;:::o;6195:279:8:-;4992:4:1;5025:20;;;:10;:20;;;;;;6297:13:8;;-1:-1:-1;;;;;5025:20:1;6328:49:8;;;;-1:-1:-1;;;6328:49:8;;23014:2:9;6328:49:8;;;22996:21:9;23053:2;23033:18;;;23026:30;-1:-1:-1;;;23072:18:9;;;23065:50;23132:18;;6328:49:8;22812:344:9;6328:49:8;6392:10;;;;6388:35;;6411:12;6404:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6195:279;;;:::o;6388:35::-;6441:25;6457:8;6441:15;:25::i;6482:369::-;6588:7;6613:19;:56;;;;;;;;;;;;;;;;;;;6680:20;6730:6;6738:7;6713:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;6703:44;;;;;;6680:67;;6758:14;6775:44;6785:12;6799:3;:5;;;6806:3;:5;;;6813:3;:5;;;6775:44;;;;;;;;;;;;;;;;;23776:25:9;;;23849:4;23837:17;;;;23832:2;23817:18;;23810:45;23886:2;23871:18;;23864:34;23929:2;23914:18;;23907:34;23763:3;23748:19;;23549:398;6775:44:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6775:44:8;;-1:-1:-1;;6775:44:8;;;6482:369;-1:-1:-1;;;;;;;6482:369:8:o;745:26:1:-;;;;;;;:::i;5981:127:8:-;483:5:6;;-1:-1:-1;;;;;483:5:6;469:10;:19;461:51;;;;-1:-1:-1;;;461:51:6;;;;;;;:::i;:::-;6047:8:8::1;:20:::0;;;::::1;;-1:-1:-1::0;;;6047:20:8::1;-1:-1:-1::0;;;;6047:20:8;;::::1;;::::0;;6083:17:::1;::::0;::::1;::::0;::::1;::::0;6058:9;565:14:9;558:22;540:41;;528:2;513:18;;400:187;7182:182:1;-1:-1:-1;;;;;7320:25:1;;;7291:4;7320:25;;;:17;:25;;;;;;;;:36;;;;;;;;;;;;;;;7182:182::o;3544:368:8:-;616:5:6;;-1:-1:-1;;;;;616:5:6;602:10;:19;;:48;;-1:-1:-1;639:10:6;625:25;;;;:13;:25;;;;;;;;602:48;580:127;;;;-1:-1:-1;;;580:127:6;;24154:2:9;580:127:6;;;24136:21:9;24193:2;24173:18;;;24166:30;24232:31;24212:18;;;24205:59;24281:18;;580:127:6;23952:353:9;580:127:6;1158:2:8::1;3656:5;:12;3640:13;;:28;;;;:::i;:::-;:47;;3632:86;;;::::0;-1:-1:-1;;;3632:86:8;;24512:2:9;3632:86:8::1;::::0;::::1;24494:21:9::0;24551:2;24531:18;;;24524:30;24590:28;24570:18;;;24563:56;24636:18;;3632:86:8::1;24310:350:9::0;3632:86:8::1;3771:12:::0;;3754:13:::1;:29:::0;;;;::::1;::::0;;:13:::1;3805:100;3822:5;:12;3820:1;:14;;;3805:100;;;3856:37;3867:5;3873:1;3867:8;;;;;;;;;;:::i;:::-;;;;;;;3877:13;17567:9:1::0;:16;;17496:95;3877:13:8::1;:15;::::0;3891:1:::1;3877:15;:::i;:::-;3856:10;:37::i;:::-;3836:3:::0;::::1;::::0;::::1;:::i;:::-;;;;3805:100;;5523:408:1::0;5592:13;5608:17;5616:8;5608:7;:17::i;:::-;5592:33;;5651:5;-1:-1:-1;;;;;5644:12:1;:3;-1:-1:-1;;;;;5644:12:1;;5636:48;;;;-1:-1:-1;;;5636:48:1;;25047:2:9;5636:48:1;;;25029:21:9;25086:2;25066:18;;;25059:30;-1:-1:-1;;;25105:18:9;;;25098:53;25168:18;;5636:48:1;24845:347:9;5636:48:1;5717:10;-1:-1:-1;;;;;5717:19:1;;;;:58;;;5740:35;5757:5;5764:10;5740:16;:35::i;:::-;5695:139;;;;-1:-1:-1;;;5695:139:1;;25399:2:9;5695:139:1;;;25381:21:9;25438:2;25418:18;;;25411:30;25477:33;25457:18;;;25450:61;25528:18;;5695:139:1;25197:355:9;5695:139:1;5847:24;;;;:14;:24;;;;;;:30;;-1:-1:-1;;;;;;5847:30:1;-1:-1:-1;;;;;5847:30:1;;;;;;;;;5893;;5847:24;;5893:30;;;;;;;5581:350;5523:408;;:::o;8092:240::-;8227:34;8245:5;8252:8;8227:17;:34::i;:::-;8219:63;;;;-1:-1:-1;;;8219:63:1;;;;;;;:::i;:::-;8293:31;8303:5;8310:3;8315:8;8293:9;:31::i;7811:184::-;7935:8;2381:39;2399:10;2411:8;2381:17;:39::i;:::-;2373:68;;;;-1:-1:-1;;;2373:68:1;;;;;;;:::i;:::-;7956:31:::1;7966:5;7973:3;7978:8;7956:9;:31::i;10279:383::-:0;10435:35;10449:5;10456:3;10461:8;10435:13;:35::i;:::-;10553:53;10578:5;10585:3;10590:8;10600:5;10553:24;:53::i;:::-;10531:123;;;;-1:-1:-1;;;10531:123:1;;26104:2:9;10531:123:1;;;26086:21:9;26143:2;26123:18;;;26116:30;-1:-1:-1;;;26162:18:9;;;26155:50;26222:18;;10531:123:1;25902:344:9;1992:106:2;2050:40;2062:17;2070:8;2062:7;:17::i;:::-;2081:8;2050:11;:40::i;4061:172:8:-;4136:7;4132:94;4149:8;4147:10;;:1;:10;;;4132:94;;;4179:35;4190:4;4196:13;17567:9:1;:16;;17496:95;4179:35:8;4159:3;;;;:::i;:::-;;;;4132:94;;1688:164:2;1766:12;:28;1781:13;1766:12;:28;:::i;:::-;;1810:34;1830:13;1810:34;;;;;;:::i;213:723:7:-;269:13;490:5;499:1;490:10;486:53;;-1:-1:-1;;517:10:7;;;;;;;;;;;;-1:-1:-1;;;517:10:7;;;;;213:723::o;486:53::-;564:5;549:12;605:78;612:9;;605:78;;638:8;;;;:::i;:::-;;-1:-1:-1;661:10:7;;-1:-1:-1;669:2:7;661:10;;:::i;:::-;;;605:78;;;693:19;725:6;715:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;715:17:7;;693:39;;743:154;750:10;;743:154;;777:11;787:1;777:11;;:::i;:::-;;-1:-1:-1;846:10:7;854:2;846:5;:10;:::i;:::-;833:24;;:2;:24;:::i;:::-;820:39;;803:6;810;803:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;803:56:7;;;;;;;;-1:-1:-1;874:11:7;883:2;874:11;;:::i;:::-;;;743:154;;;921:6;213:723;-1:-1:-1;;;;213:723:7:o;6598:253:1:-;6690:10;-1:-1:-1;;;;;6683:17:1;;;6675:53;;;;-1:-1:-1;;;6675:53:1;;25047:2:9;6675:53:1;;;25029:21:9;25086:2;25066:18;;;25059:30;-1:-1:-1;;;25105:18:9;;;25098:53;25168:18;;6675:53:1;24845:347:9;6675:53:1;6757:10;6739:29;;;;:17;:29;;;;;;;;-1:-1:-1;;;;;6739:34:1;;;;;;;;;;;;:46;;-1:-1:-1;;6739:46:1;;;;;;;;;;6801:42;;540:41:9;;;6739:34:1;;6757:10;6801:42;;513:18:9;6801:42:1;;;;;;;6598:253;;:::o;1860:124:2:-;1950:26;1962:3;1967:8;1950:11;:26::i;11034:474:1:-;11147:4;11169:13;11185:17;11193:8;11185:7;:17::i;:::-;11169:33;;11394:5;-1:-1:-1;;;;;11382:17:1;:8;-1:-1:-1;;;;;11382:17:1;;:67;;;-1:-1:-1;6237:7:1;6264:24;;;:14;:24;;;;;;-1:-1:-1;;;;;11416:33:1;;;6264:24;;11416:33;11382:67;:117;;;;11466:33;11483:5;11490:8;11466:16;:33::i;8340:348::-;-1:-1:-1;;;;;8466:17:1;;8458:54;;;;-1:-1:-1;;;8458:54:1;;;;;;;:::i;:::-;8523:30;8537:5;8544:8;8523:13;:30::i;:::-;8564:32;8580:5;8587:8;8564:15;:32::i;:::-;8607:25;8618:3;8623:8;8607:10;:25::i;:::-;8671:8;8666:3;-1:-1:-1;;;;;8650:30:1;8659:5;-1:-1:-1;;;;;8650:30:1;;;;;;;;;;;8340:348;;;:::o;16288:428::-;16449:4;16471:16;:3;-1:-1:-1;;;;;16471:14:1;;:16::i;:::-;16466:61;;-1:-1:-1;16511:4:1;16504:11;;16466:61;16553:110;;-1:-1:-1;;;16553:110:1;;16537:13;;-1:-1:-1;;;;;16553:36:1;;;;;:110;;16604:5;;16624:8;;16647:5;;16553:110;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;16682:25:1;-1:-1:-1;;;16682:25:1;;-1:-1:-1;;16288:428:1;;;;;;:::o;12927:335::-;13015:8;2381:39;2399:10;2411:8;2381:17;:39::i;:::-;2373:68;;;;-1:-1:-1;;;2373:68:1;;;;;;;:::i;:::-;13041:31:::1;13055:6;13063:8;13041:13;:31::i;:::-;13083:33;13099:6;13107:8;13083:15;:33::i;:::-;13127:29;13147:8;13127:19;:29::i;:::-;13198:1;13167:20:::0;;;:10:::1;:20;::::0;;;;;:33;;-1:-1:-1;;;;;;13167:33:1::1;::::0;;13216:38;13178:8;;13198:1;-1:-1:-1;;;;;13216:38:1;::::1;::::0;::::1;::::0;13198:1;;13216:38:::1;12927:335:::0;;;:::o;11779:367::-;-1:-1:-1;;;;;11853:17:1;;11845:54;;;;-1:-1:-1;;;11845:54:1;;;;;;;:::i;:::-;4992:4;5025:20;;;:10;:20;;;;;;-1:-1:-1;;;;;5025:20:1;5063:19;11910:50;;;;-1:-1:-1;;;11910:50:1;;29550:2:9;11910:50:1;;;29532:21:9;29589:2;29569:18;;;29562:30;-1:-1:-1;;;29608:18:9;;;29601:50;29668:18;;11910:50:1;29348:344:9;11910:50:1;11971:25;11982:3;11987:8;11971:10;:25::i;:::-;12034:9;:16;;12007:24;;;;:14;:24;;;;;;:43;;;12061:24;;;;;;;;;;;;;;;12103:35;;12022:8;;-1:-1:-1;;;;;12103:35:1;;;;;12007:24;;12103:35;11779:367;;:::o;13546:374::-;13666:6;-1:-1:-1;;;;;13645:27:1;:17;13653:8;13645:7;:17::i;:::-;-1:-1:-1;;;;;13645:27:1;;13623:113;;;;-1:-1:-1;;;13623:113:1;;29899:2:9;13623:113:1;;;29881:21:9;29938:2;29918:18;;;29911:30;29977:34;29957:18;;;29950:62;-1:-1:-1;;;30028:18:9;;;30021:34;30072:19;;13623:113:1;29697:400:9;13623:113:1;13787:1;13751:24;;;:14;:24;;;;;;-1:-1:-1;;;;;13751:24:1;:38;13747:166;;13841:1;13806:24;;;:14;:24;;;;;;:37;;-1:-1:-1;;;;;;13806:37:1;;;13863:38;13821:8;;13841:1;-1:-1:-1;;;;;13863:38:1;;;;;13841:1;;13863:38;13546:374;;:::o;14869:882::-;-1:-1:-1;;;;;14972:23:1;;14947:22;14972:23;;;:16;:23;;;;;;:27;;14998:1;;14972:27;:::i;:::-;15010:18;15031:26;;;:16;:26;;;;;;14947:52;;-1:-1:-1;15154:28:1;;;15151:324;;-1:-1:-1;;;;;15221:18:1;;15199:19;15221:18;;;:11;:18;;;;;;;;:34;;;;;;;;;15270:30;;;;;;:44;;;15387:29;;:16;:29;;;;;:42;;;15151:324;15569:26;;;;:16;:26;;;;;;;;15562:33;;;-1:-1:-1;;;;;15613:18:1;;;;;:11;:18;;;;;:34;;;;;;;;15606:41;;;15684:23;;:16;:23;;;;;;:25;;15708:1;;15684:25;:::i;:::-;-1:-1:-1;;;;;15658:23:1;;;;;;;:16;:23;;;;;:51;;;;-1:-1:-1;;;14869:882:1:o;14202:369::-;14273:14;14290;14300:3;14290:9;:14::i;:::-;-1:-1:-1;;;;;14315:16:1;;;;;;:11;:16;;;;;;;;:24;;;;;;;;:35;;;14361:26;;;:16;:26;;;;;:35;;;14431:21;;;:16;:21;;;;14273:31;;-1:-1:-1;14431:25:1;;14455:1;14431:25;:::i;:::-;-1:-1:-1;;;;;14407:21:1;;;;;;;:16;:21;;;;;;;;:49;;;;14503:20;;;:10;:20;;;;;;;:26;;-1:-1:-1;;;;;;14503:26:1;;;;;;;-1:-1:-1;14202:369:1:o;496:641:0:-;556:4;1037:20;;867:66;1086:23;;;;;;:42;;-1:-1:-1;;1113:15:0;;;1078:51;-1:-1:-1;;496:641:0:o;12154:568:1:-;12244:9;:16;12219:22;;12244:20;;12263:1;;12244:20;:::i;:::-;12275:18;12296:23;;;:14;:23;;;;;;12352:9;:25;;12219:45;;-1:-1:-1;12296:23:1;;12219:45;;12352:25;;;;;;:::i;:::-;;;;;;;;;12330:47;;12414:11;12390:9;12400:10;12390:21;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;12494:27;;;:14;:27;;;;;;;:40;;;12665:23;;;;;12658:30;12699:9;:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;12208:514;;;12154:568;:::o;14:131:9:-;-1:-1:-1;;;;;;88:32:9;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;:::-;384:5;150:245;-1:-1:-1;;;150:245:9:o;592:250::-;677:1;687:113;701:6;698:1;695:13;687:113;;;777:11;;;771:18;758:11;;;751:39;723:2;716:10;687:113;;;-1:-1:-1;;834:1:9;816:16;;809:27;592:250::o;847:271::-;889:3;927:5;921:12;954:6;949:3;942:19;970:76;1039:6;1032:4;1027:3;1023:14;1016:4;1009:5;1005:16;970:76;:::i;:::-;1100:2;1079:15;-1:-1:-1;;1075:29:9;1066:39;;;;1107:4;1062:50;;847:271;-1:-1:-1;;847:271:9:o;1123:220::-;1272:2;1261:9;1254:21;1235:4;1292:45;1333:2;1322:9;1318:18;1310:6;1292:45;:::i;1348:180::-;1407:6;1460:2;1448:9;1439:7;1435:23;1431:32;1428:52;;;1476:1;1473;1466:12;1428:52;-1:-1:-1;1499:23:9;;1348:180;-1:-1:-1;1348:180:9:o;1741:131::-;-1:-1:-1;;;;;1816:31:9;;1806:42;;1796:70;;1862:1;1859;1852:12;1877:315;1945:6;1953;2006:2;1994:9;1985:7;1981:23;1977:32;1974:52;;;2022:1;2019;2012:12;1974:52;2061:9;2048:23;2080:31;2105:5;2080:31;:::i;:::-;2130:5;2182:2;2167:18;;;;2154:32;;-1:-1:-1;;;1877:315:9:o;2197:247::-;2256:6;2309:2;2297:9;2288:7;2284:23;2280:32;2277:52;;;2325:1;2322;2315:12;2277:52;2364:9;2351:23;2383:31;2408:5;2383:31;:::i;2631:127::-;2692:10;2687:3;2683:20;2680:1;2673:31;2723:4;2720:1;2713:15;2747:4;2744:1;2737:15;2763:275;2834:2;2828:9;2899:2;2880:13;;-1:-1:-1;;2876:27:9;2864:40;;2934:18;2919:34;;2955:22;;;2916:62;2913:88;;;2981:18;;:::i;:::-;3017:2;3010:22;2763:275;;-1:-1:-1;2763:275:9:o;3043:114::-;3127:4;3120:5;3116:16;3109:5;3106:27;3096:55;;3147:1;3144;3137:12;3162:611;3218:5;3266:4;3254:9;3249:3;3245:19;3241:30;3238:50;;;3284:1;3281;3274:12;3238:50;3317:2;3311:9;3359:4;3351:6;3347:17;3430:6;3418:10;3415:22;3394:18;3382:10;3379:34;3376:62;3373:88;;;3441:18;;:::i;:::-;3481:10;3477:2;3470:22;;3510:6;3501:15;;3553:9;3540:23;3532:6;3525:39;3625:2;3614:9;3610:18;3597:32;3592:2;3584:6;3580:15;3573:57;3682:2;3671:9;3667:18;3654:32;3695:31;3718:7;3695:31;:::i;:::-;3754:2;3742:15;;;;3735:32;3162:611;;-1:-1:-1;;3162:611:9:o;3778:645::-;3900:6;3908;3916;3924;3932;3985:3;3973:9;3964:7;3960:23;3956:33;3953:53;;;4002:1;3999;3992:12;3953:53;4041:9;4028:23;4060:31;4085:5;4060:31;:::i;:::-;4110:5;-1:-1:-1;4167:2:9;4152:18;;4139:32;4180:33;4139:32;4180:33;:::i;:::-;4232:7;-1:-1:-1;4286:2:9;4271:18;;4258:32;;-1:-1:-1;4337:2:9;4322:18;;4309:32;;-1:-1:-1;4360:57:9;4409:7;4403:3;4388:19;;4360:57;:::i;:::-;4350:67;;3778:645;;;;;;;;:::o;4428:456::-;4505:6;4513;4521;4574:2;4562:9;4553:7;4549:23;4545:32;4542:52;;;4590:1;4587;4580:12;4542:52;4629:9;4616:23;4648:31;4673:5;4648:31;:::i;:::-;4698:5;-1:-1:-1;4755:2:9;4740:18;;4727:32;4768:33;4727:32;4768:33;:::i;:::-;4428:456;;4820:7;;-1:-1:-1;;;4874:2:9;4859:18;;;;4846:32;;4428:456::o;4889:452::-;4964:6;4972;4980;5033:2;5021:9;5012:7;5008:23;5004:32;5001:52;;;5049:1;5046;5039:12;5001:52;5088:9;5075:23;5107:31;5132:5;5107:31;:::i;:::-;5157:5;-1:-1:-1;5214:2:9;5199:18;;5186:32;5227:31;5186:32;5227:31;:::i;5346:407::-;5411:5;5445:18;5437:6;5434:30;5431:56;;;5467:18;;:::i;:::-;5505:57;5550:2;5529:15;;-1:-1:-1;;5525:29:9;5556:4;5521:40;5505:57;:::i;:::-;5496:66;;5585:6;5578:5;5571:21;5625:3;5616:6;5611:3;5607:16;5604:25;5601:45;;;5642:1;5639;5632:12;5601:45;5691:6;5686:3;5679:4;5672:5;5668:16;5655:43;5745:1;5738:4;5729:6;5722:5;5718:18;5714:29;5707:40;5346:407;;;;;:::o;5758:451::-;5827:6;5880:2;5868:9;5859:7;5855:23;5851:32;5848:52;;;5896:1;5893;5886:12;5848:52;5936:9;5923:23;5969:18;5961:6;5958:30;5955:50;;;6001:1;5998;5991:12;5955:50;6024:22;;6077:4;6069:13;;6065:27;-1:-1:-1;6055:55:9;;6106:1;6103;6096:12;6055:55;6129:74;6195:7;6190:2;6177:16;6172:2;6168;6164:11;6129:74;:::i;6214:384::-;6280:6;6288;6341:2;6329:9;6320:7;6316:23;6312:32;6309:52;;;6357:1;6354;6347:12;6309:52;6396:9;6383:23;6415:31;6440:5;6415:31;:::i;:::-;6465:5;-1:-1:-1;6522:2:9;6507:18;;6494:32;6535:31;6494:32;6535:31;:::i;:::-;6585:7;6575:17;;;6214:384;;;;;:::o;6827:118::-;6913:5;6906:13;6899:21;6892:5;6889:32;6879:60;;6935:1;6932;6925:12;6950:382;7015:6;7023;7076:2;7064:9;7055:7;7051:23;7047:32;7044:52;;;7092:1;7089;7082:12;7044:52;7131:9;7118:23;7150:31;7175:5;7150:31;:::i;:::-;7200:5;-1:-1:-1;7257:2:9;7242:18;;7229:32;7270:30;7229:32;7270:30;:::i;7337:795::-;7432:6;7440;7448;7456;7509:3;7497:9;7488:7;7484:23;7480:33;7477:53;;;7526:1;7523;7516:12;7477:53;7565:9;7552:23;7584:31;7609:5;7584:31;:::i;:::-;7634:5;-1:-1:-1;7691:2:9;7676:18;;7663:32;7704:33;7663:32;7704:33;:::i;:::-;7756:7;-1:-1:-1;7810:2:9;7795:18;;7782:32;;-1:-1:-1;7865:2:9;7850:18;;7837:32;7892:18;7881:30;;7878:50;;;7924:1;7921;7914:12;7878:50;7947:22;;8000:4;7992:13;;7988:27;-1:-1:-1;7978:55:9;;8029:1;8026;8019:12;7978:55;8052:74;8118:7;8113:2;8100:16;8095:2;8091;8087:11;8052:74;:::i;:::-;8042:84;;;7337:795;;;;;;;:::o;8137:300::-;8232:6;8240;8293:3;8281:9;8272:7;8268:23;8264:33;8261:53;;;8310:1;8307;8300:12;8261:53;8346:9;8333:23;8323:33;;8375:56;8423:7;8418:2;8407:9;8403:18;8375:56;:::i;:::-;8365:66;;8137:300;;;;;:::o;8442:241::-;8498:6;8551:2;8539:9;8530:7;8526:23;8522:32;8519:52;;;8567:1;8564;8557:12;8519:52;8606:9;8593:23;8625:28;8647:5;8625:28;:::i;8688:388::-;8756:6;8764;8817:2;8805:9;8796:7;8792:23;8788:32;8785:52;;;8833:1;8830;8823:12;8785:52;8872:9;8859:23;8891:31;8916:5;8891:31;:::i;:::-;8941:5;-1:-1:-1;8998:2:9;8983:18;;8970:32;9011:33;8970:32;9011:33;:::i;9081:1021::-;9165:6;9196:2;9239;9227:9;9218:7;9214:23;9210:32;9207:52;;;9255:1;9252;9245:12;9207:52;9295:9;9282:23;9324:18;9365:2;9357:6;9354:14;9351:34;;;9381:1;9378;9371:12;9351:34;9419:6;9408:9;9404:22;9394:32;;9464:7;9457:4;9453:2;9449:13;9445:27;9435:55;;9486:1;9483;9476:12;9435:55;9522:2;9509:16;9544:2;9540;9537:10;9534:36;;;9550:18;;:::i;:::-;9596:2;9593:1;9589:10;9579:20;;9619:28;9643:2;9639;9635:11;9619:28;:::i;:::-;9681:15;;;9751:11;;;9747:20;;;9712:12;;;;9779:19;;;9776:39;;;9811:1;9808;9801:12;9776:39;9835:11;;;;9855:217;9871:6;9866:3;9863:15;9855:217;;;9951:3;9938:17;9925:30;;9968:31;9993:5;9968:31;:::i;:::-;10012:18;;;9888:12;;;;10050;;;;9855:217;;;10091:5;9081:1021;-1:-1:-1;;;;;;;;9081:1021:9:o;10107:380::-;10186:1;10182:12;;;;10229;;;10250:61;;10304:4;10296:6;10292:17;10282:27;;10250:61;10357:2;10349:6;10346:14;10326:18;10323:38;10320:161;;10403:10;10398:3;10394:20;10391:1;10384:31;10438:4;10435:1;10428:15;10466:4;10463:1;10456:15;10320:161;;10107:380;;;:::o;10492:339::-;10694:2;10676:21;;;10733:2;10713:18;;;10706:30;-1:-1:-1;;;10767:2:9;10752:18;;10745:45;10822:2;10807:18;;10492:339::o;13286:127::-;13347:10;13342:3;13338:20;13335:1;13328:31;13378:4;13375:1;13368:15;13402:4;13399:1;13392:15;13418:128;13485:9;;;13506:11;;;13503:37;;;13520:18;;:::i;13551:125::-;13616:9;;;13637:10;;;13634:36;;;13650:18;;:::i;14017:168::-;14057:7;14123:1;14119;14115:6;14111:14;14108:1;14105:21;14100:1;14093:9;14086:17;14082:45;14079:71;;;14130:18;;:::i;:::-;-1:-1:-1;14170:9:9;;14017:168::o;14875:245::-;14942:6;14995:2;14983:9;14974:7;14970:23;14966:32;14963:52;;;15011:1;15008;15001:12;14963:52;15043:9;15037:16;15062:28;15084:5;15062:28;:::i;15471:251::-;15541:6;15594:2;15582:9;15573:7;15569:23;15565:32;15562:52;;;15610:1;15607;15600:12;15562:52;15642:9;15636:16;15661:31;15686:5;15661:31;:::i;16131:247::-;16199:6;16252:2;16240:9;16231:7;16227:23;16223:32;16220:52;;;16268:1;16265;16258:12;16220:52;16300:9;16294:16;16319:29;16342:5;16319:29;:::i;16383:148::-;16471:4;16450:12;;;16464;;;16446:31;;16489:13;;16486:39;;;16505:18;;:::i;17143:127::-;17204:10;17199:3;17195:20;17192:1;17185:31;17235:4;17232:1;17225:15;17259:4;17256:1;17249:15;17275:343;17477:2;17459:21;;;17516:2;17496:18;;;17489:30;-1:-1:-1;;;17550:2:9;17535:18;;17528:49;17609:2;17594:18;;17275:343::o;18382:348::-;18584:2;18566:21;;;18623:2;18603:18;;;18596:30;18662:26;18657:2;18642:18;;18635:54;18721:2;18706:18;;18382:348::o;19091:135::-;19130:3;19151:17;;;19148:43;;19171:18;;:::i;:::-;-1:-1:-1;19218:1:9;19207:13;;19091:135::o;20640:722::-;20690:3;20731:5;20725:12;20760:36;20786:9;20760:36;:::i;:::-;20815:1;20832:18;;;20859:133;;;;21006:1;21001:355;;;;20825:531;;20859:133;-1:-1:-1;;20892:24:9;;20880:37;;20965:14;;20958:22;20946:35;;20937:45;;;-1:-1:-1;20859:133:9;;21001:355;21032:5;21029:1;21022:16;21061:4;21106:2;21103:1;21093:16;21131:1;21145:165;21159:6;21156:1;21153:13;21145:165;;;21237:14;;21224:11;;;21217:35;21280:16;;;;21174:10;;21145:165;;;21149:3;;;21339:6;21334:3;21330:16;21323:23;;20825:531;;;;;20640:722;;;;:::o;21367:469::-;21588:3;21616:38;21650:3;21642:6;21616:38;:::i;:::-;21683:6;21677:13;21699:65;21757:6;21753:2;21746:4;21738:6;21734:17;21699:65;:::i;:::-;21780:50;21822:6;21818:2;21814:15;21806:6;21780:50;:::i;:::-;21773:57;21367:469;-1:-1:-1;;;;;;;21367:469:9:o;21841:357::-;22059:3;22084:108;22118:73;22152:38;22186:3;22178:6;22152:38;:::i;:::-;22144:6;22118:73;:::i;:::-;22110:6;22084:108;:::i;:::-;22077:115;21841:357;-1:-1:-1;;;;;21841:357:9:o;23161:383::-;23318:3;23356:6;23350:13;23372:66;23431:6;23426:3;23419:4;23411:6;23407:17;23372:66;:::i;:::-;23460:16;;;;23485:21;;;-1:-1:-1;23533:4:9;23522:16;;23161:383;-1:-1:-1;23161:383:9:o;24665:175::-;24702:3;24746:4;24739:5;24735:16;24775:4;24766:7;24763:17;24760:43;;24783:18;;:::i;:::-;24832:1;24819:15;;24665:175;-1:-1:-1;;24665:175:9:o;25557:340::-;25759:2;25741:21;;;25798:2;25778:18;;;25771:30;-1:-1:-1;;;25832:2:9;25817:18;;25810:46;25888:2;25873:18;;25557:340::o;26251:545::-;26353:2;26348:3;26345:11;26342:448;;;26389:1;26414:5;26410:2;26403:17;26459:4;26455:2;26445:19;26529:2;26517:10;26513:19;26510:1;26506:27;26500:4;26496:38;26565:4;26553:10;26550:20;26547:47;;;-1:-1:-1;26588:4:9;26547:47;26643:2;26638:3;26634:12;26631:1;26627:20;26621:4;26617:31;26607:41;;26698:82;26716:2;26709:5;26706:13;26698:82;;;26761:17;;;26742:1;26731:13;26698:82;;;26702:3;;;26251:545;;;:::o;26972:1352::-;27098:3;27092:10;27125:18;27117:6;27114:30;27111:56;;;27147:18;;:::i;:::-;27176:97;27266:6;27226:38;27258:4;27252:11;27226:38;:::i;:::-;27220:4;27176:97;:::i;:::-;27328:4;;27392:2;27381:14;;27409:1;27404:663;;;;28111:1;28128:6;28125:89;;;-1:-1:-1;28180:19:9;;;28174:26;28125:89;-1:-1:-1;;26929:1:9;26925:11;;;26921:24;26917:29;26907:40;26953:1;26949:11;;;26904:57;28227:81;;27374:944;;27404:663;20587:1;20580:14;;;20624:4;20611:18;;-1:-1:-1;;27440:20:9;;;27558:236;27572:7;27569:1;27566:14;27558:236;;;27661:19;;;27655:26;27640:42;;27753:27;;;;27721:1;27709:14;;;;27588:19;;27558:236;;;27562:3;27822:6;27813:7;27810:19;27807:201;;;27883:19;;;27877:26;-1:-1:-1;;27966:1:9;27962:14;;;27978:3;27958:24;27954:37;27950:42;27935:58;27920:74;;27807:201;-1:-1:-1;;;;;28054:1:9;28038:14;;;28034:22;28021:36;;-1:-1:-1;26972:1352:9:o;28329:127::-;28390:10;28385:3;28381:20;28378:1;28371:31;28421:4;28418:1;28411:15;28445:4;28442:1;28435:15;28461:120;28501:1;28527;28517:35;;28532:18;;:::i;:::-;-1:-1:-1;28566:9:9;;28461:120::o;28586:112::-;28618:1;28644;28634:35;;28649:18;;:::i;:::-;-1:-1:-1;28683:9:9;;28586:112::o;28703:386::-;28935:1;28931;28926:3;28922:11;28918:19;28910:6;28906:32;28895:9;28888:51;28975:6;28970:2;28959:9;28955:18;28948:34;29018:2;29013;29002:9;28998:18;28991:30;28869:4;29038:45;29079:2;29068:9;29064:18;29056:6;29038:45;:::i;29094:249::-;29163:6;29216:2;29204:9;29195:7;29191:23;29187:32;29184:52;;;29232:1;29229;29222:12;29184:52;29264:9;29258:16;29283:30;29307:5;29283:30;:::i;30102:127::-;30163:10;30158:3;30154:20;30151:1;30144:31;30194:4;30191:1;30184:15;30218:4;30215:1;30208:15

Swarm Source

ipfs://c98077b88d5b3c8a87e109dd5ec09e586b9eee9ad7d157be620b998fe0814541
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.