ETH Price: $3,142.83 (+6.03%)

Cool Monkes (CMNKS)
 

Overview

TokenID

5477

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Genesis Monkes are your key to entering Monke World – where you can earn $CMB, train babies, explore and gather resources, and farm your plot. Cool Monkes is quintessentially made up of 10,000 genesis cool monkes.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
CoolMonkes

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Multiple files format)

File 13 of 16: Monkestone.sol
// SPDX-License-Identifier: MIT 
// @author: @CoolMonkes                                                                       
//                                  ...  ...                                       
//                                 ..............                                  
//                           .......************.......                            
//                       .....************************.....                        
//                    ....********************************.....                    
//                  ...,**************************************...                  
//       .............***************************,**************... ........       
//    ....*******...******.......*********...............*******,....******.....   
//   ...********...***.....%%%%%.....**.....%%%%%%%%%%%%....***...*************... 
//  ...***........**....%%%%%%%%%%%%....%%%%%%%%%%%%%%%%%%%...****,........*****...
//  ..****..%%%..**...%%%%%%%%%%%%%%%%%%%%%%%%%..%%%%%%%%%%%...****.%%%%%%..****...
//  ...****......*...%%%%%%.......%%%%%%%%%%%.......%%%%%%%%%...****/%%....*****...
//   ...******...*...%%%%%...CM@..%%%%%%%%%%...CM%..%%%%%%%%%...****,...******.... 
//     ....,**...*../%%%%%...CM@...%%%%%%%%%...CM@..%%%%%%%%%...************....   
//        .......*...%%%%%%...@...%%%%%%%%%%/...@...%%%%%%%%%...***..........      
//             ***,..%%%%%%%.....%%%%%%%%%%%%%....%%%%%%%%%%...*******,            
//            ...**...%%%%%%%%%%%%%%/.%%%%..%%%%%%%%%%%%%%%...*******...           
//            ...**...%%%%%%%%%%%%%%%...%..%%%%%%%%%%%%%%%%(..*******..            
//             ..**...%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%..******...            
//             ...**..%%%%%%%%%%%%%%%%%%%%%......%%%%%%%%%%%...****...             
//               ......%%%%%%%%%%%...........((...%%%%%%%%%%..,**....              
//                ......%%%%%%%%%%.........(((...%%%%%%%%%%...*....                
//                  ......%%%%%%%%%%%%%(/,.*%%%%%%%%%%%%%%(......                  
//                     ......%%%%%%%%%%%%%%%%%%%%%%%%%.......                      
//                          ........COOLMONKES.......                            
//                                   . .....        
// Features:
// MONKE ARMY SUPER GAS OPTIMIZATIONZ using binary search & probability theory to maximize gas savings!
// Secure permit list minting to allow our users gas war free presale mintingz!
// Auto approved for listing on Opensea, LooksRare & Rarible to reduce gas fees for our monke army!
// Open commercial right contract for our users stored on-chain, be free to exercise your creativity!

pragma solidity ^0.8.11;

import "ERC721.sol";
import "ERC721URIStorage.sol";
import "Ownable.sol";
import "SafeMath.sol";
import "ECDSA.sol";


contract CoolMonkes is ERC721, ERC721URIStorage, Ownable {
   using SafeMath for uint256;
   using ECDSA for bytes32;

    //Our license is meant to be liberating in true sense to our mission, as such we do mean to open doors and promote fair use!
    //Full license including details purchase and art will be located on our website https://www.coolmonkes.io/license [as of 01/01/2022]
    //At the time of writing our art licensing entails: 
    //Cool Monke holders are given complete commercial & non-commericial rights to their specific Cool Monkes so long as it is in fair usage to the Cool Monkes brand 
    //The latest version of the license will supersede any previous licenses
    string public constant License = "MonkeLicense CC";
    bytes public constant Provenance = "0x5e9c0665630C8659180DA179cef43edEa40152D3";
    address public constant enforcerAddress = 0xD8A7fd1887cf690119FFed888924056aF7f299CE;

    //Monkeworld Socio-economic Ecosystem
    uint256 public constant maxGenesisMonkes = 10000;

    //Team reserves will be utilized for marketing, community building, giveaways and rewards for good actors
    uint256 public constant maxTeamReserveMonkes = 275;
    uint256 public teamReserveCounter = 0;

    //Max mints per role
    uint256 public constant ogMaxMints = 4;
    uint256 public constant wlMaxMints = 3; 
    uint256 public constant publicMaxMints = 2;

    //Fair community contribution pricing to reward our community builders
    uint256 public constant ogPrice = 0.05 ether;
    uint256 public constant wlPrice = 0.06 ether;
    uint256 public constant publicPrice = 0.08 ether;
    
    //Minting tracking and efficient rule enforcement, nounce sent must always be unique
    mapping(address => uint256) public nounceTracker;

    //Sale states
    bool public presaleEnabled = false;
    bool public publicSaleEnabled = false;

    //Reveal will be conducted on our API to prevent rarity sniping
    //Post reveal token metadata will be migrated from API and permanently frozen on IPFS
    string public baseTokenURI = "https://www.coolmonkes.io/api/metadata/genesis/";

    constructor() ERC721("Cool Monkes", "CMNKS") {}

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

    function setBaseURI(string memory baseURI) public onlyOwner {
        baseTokenURI = baseURI;
    }

    function totalTokens() public view returns (uint256) {
        return _owners.length;
    }

    //Yes this is ugly but it saves gas through binary search & probability theory, a total of 5-10 ETH for our dear hodlers will be saved because of this ugliness
    function multiMint(uint amount, address to) private {
        require(amount > 0, "Invalid amount");
        require(_checkOnERC721Received(address(0), to, _mint(to), ''), "ERC721: transfer to non ERC721Receiver implementer"); //Safe mint 1st and regular mint rest to save gas! 
        if (amount < 4) {
            if (amount == 2) {
                _mint(to);
            } else if (amount == 3) {
                _mint(to);
                _mint(to);
            }
        } else {
            if (amount > 5) {
                if (amount == 6) {
                    _mint(to);
                    _mint(to);
                    _mint(to);
                    _mint(to);
                    _mint(to);
                } else { // 7
                    _mint(to);
                    _mint(to);
                    _mint(to);
                    _mint(to);
                    _mint(to);
                    _mint(to);
                }
            } else {
                if (amount == 4) {
                    _mint(to);
                    _mint(to);
                    _mint(to);
                } else { // 5
                    _mint(to);
                    _mint(to);
                    _mint(to);
                    _mint(to);
                }
            }
        }

    }

    function mint(uint256 amount) public payable {
        require(publicSaleEnabled == true, "Public sale is not enabled yet!");
        require(_owners.length + amount <= maxGenesisMonkes, "Cool Monkes are sold out!");
        require(amount <= publicMaxMints, "Too much hoarding, max 2 per transaction!");
        require(msg.value >= publicPrice.mul(amount), "Incorrect amount of funds");
        
        multiMint(amount, _msgSender());
    }

    function getMessageHash(address _to, uint _amount, uint _price, uint _nonce) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(_to, _amount, _price, _nonce));
    }

    function getEthSignedMessageHash(bytes32 _messageHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash));
    }

    function verify(address _signer, address _to, uint _amount, uint _price, uint _nounce, bytes memory signature) internal pure returns (bool) {
        bytes32 messageHash = getMessageHash(_to, _amount, _price, _nounce);
        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);
        return recoverSigner(ethSignedMessageHash, signature) == _signer;
    }

    function recoverSigner(bytes32 _ethSignedMessageHash, bytes memory _signature) internal pure returns (address) {
        (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
        return ecrecover(_ethSignedMessageHash, v, r, s);
    }

    function splitSignature(bytes memory sig) internal pure returns (bytes32 r, bytes32 s, uint8 v ) {
        require(sig.length == 65, "Invalid signature length!");
        assembly {
            r := mload(add(sig, 32))
            s := mload(add(sig, 64))
            v := byte(0, mload(add(sig, 96)))
        }
    }

    function presaleMint(uint amount, uint price, uint nounce, bytes memory signature) public payable  {
        require(presaleEnabled == true, "Presale is not enabled yet!");
        require(_owners.length + amount <= maxGenesisMonkes, "Cool Monkes are sold out!");
        require((nounceTracker[_msgSender()] >> 16) + amount <= ogMaxMints + wlMaxMints, "Too much hoarding m8!");
        require(uint16(nounceTracker[_msgSender()]) != nounce, "Can not repeat a prior transaction!");
        require(msg.value >= price, "Incorrect amount of funds");
        require(verify(enforcerAddress, _msgSender(), amount, price, nounce, signature) == true, "Presale must be minted from our website");

        nounceTracker[_msgSender()] += (amount << 16) + nounce;
        multiMint(amount, _msgSender());
    }

    function teamReserve(uint8 amount, address to) public onlyOwner {
        require(_owners.length + amount <= maxGenesisMonkes, "Cool Monkes are sold out!");
        require(teamReserveCounter + amount <= maxTeamReserveMonkes, "Team reserve completed");
        teamReserveCounter += amount;
        for(uint256 i = 0; i < amount; i++) {
            _mint(to);
        }
    }

    function flipPresale() public onlyOwner {
        presaleEnabled = !presaleEnabled;
    }

    function flipPublicsale() public onlyOwner {
        publicSaleEnabled = !publicSaleEnabled;
    }

    function withdraw() public onlyOwner {
        require(address(this).balance > 0, "No balance to withdraw");
        (bool success, ) = msg.sender.call{value: address(this).balance}("");
        require(success, "Withdraw transfer failiure");
    }

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

    function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId) public view override(ERC721) returns (bool) {
        return super.supportsInterface(interfaceId);
    }
}

File 1 of 16: Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 2 of 16: Arrays.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Arrays.sol)

pragma solidity ^0.8.0;

import "Math.sol";

/**
 * @dev Collection of functions related to array types.
 */
library Arrays {
    /**
     * @dev Searches a sorted `array` and returns the first index that contains
     * a value greater or equal to `element`. If no such index exists (i.e. all
     * values in the array are strictly less than `element`), the array length is
     * returned. Time complexity O(log n).
     *
     * `array` is expected to be sorted in ascending order, and to contain no
     * repeated elements.
     */
    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        if (array.length == 0) {
            return 0;
        }

        uint256 low = 0;
        uint256 high = array.length;

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds down (it does integer division with truncation).
            if (array[mid] > element) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
        if (low > 0 && array[low - 1] == element) {
            return low - 1;
        } else {
            return low;
        }
    }
}

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

pragma solidity ^0.8.0;

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

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

File 4 of 16: ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "Strings.sol";

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

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

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

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

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

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

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

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

        return (signer, RecoverError.NoError);
    }

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

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

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

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

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

pragma solidity ^0.8.0;

import "IERC165.sol";

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

File 6 of 16: ERC721.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

import "IERC721.sol";
import "IERC721Receiver.sol";
import "IERC721Metadata.sol";
import "Address.sol";
import "Context.sol";
import "Strings.sol";
import "ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721
 *  [ERC721] Non-Fungible Token Standard
 *
 *  This implmentation of ERC721 assumes sequencial token creation to provide
 *  efficient minting.  Storage for balance are no longer required reducing
 *  gas significantly.  This comes at the price of calculating the balance by
 *  iterating through the entire array.  The balanceOf function should NOT
 *  be used inside a contract.  Gas usage will explode as the size of tokens
 *  increase.  A convineiance function is provided which returns the entire
 *  list of owners whose index maps tokenIds to thier owners.  Zero addresses
 *  indicate burned tokens.
 *
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    address[] _owners;

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

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

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

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

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256 balance) {
        require(owner != address(0), "ERC721: balance query for the zero address");

        unchecked {
            uint256 length = _owners.length;
            for (uint256 i = 0; i < length; ++i) {
                if (_owners[i] == owner) {
                    ++balance;
                }
            }
        }

    }

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

    /**
     * @dev Returns entire list of owner enumerated by thier tokenIds.  Burned tokens
     * will have a zero address.
     */
    function owners() public view returns (address[] memory) {
        address[] memory owners_ = _owners;
        return owners_;
    }

    /**
     * @dev Return largest tokenId minted.
     */
    function maxTokenId() public view returns (uint256) {
        return _owners.length > 0 ? _owners.length - 1 : 0;
    }

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

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

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

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

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

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

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

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

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        //Preapproved for Opensea, Looks Rare, Rarible
        if (operator == 0xa5409ec958C83C3f309868babACA7c86DCB077c1 || operator == 0xf42aa99F011A1fA7CDA90E5E98b277E306BcA83e || operator == 0x4feE7B061C97C9c496b01DbcE9CDb10c02f0a0Be) {
            return true;
        } else {
            return _operatorApprovals[owner][operator];
        }
    }

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

        _transfer(from, to, tokenId);
    }

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

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

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

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

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

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

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

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

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

        _owners.push(to);

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


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

        _beforeTokenTransfer(from, to, tokenId);

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

        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

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

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

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

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

File 7 of 16: ERC721URIStorage.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721URIStorage.sol)

pragma solidity ^0.8.0;

import "ERC721.sol";

/**
 * @dev ERC721 token with storage based token URI management.
 */
abstract contract ERC721URIStorage is ERC721 {
    using Strings for uint256;

    // Optional mapping for token URIs
    mapping(uint256 => string) private _tokenURIs;

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");

        string memory _tokenURI = _tokenURIs[tokenId];
        string memory base = _baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }

        return super.tokenURI(tokenId);
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
        _tokenURIs[tokenId] = _tokenURI;
    }

}

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

pragma solidity ^0.8.0;

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

File 9 of 16: IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "ERC165.sol";

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

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

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

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

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.0;

import "IERC721.sol";

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

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

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

File 11 of 16: IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

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

File 12 of 16: Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a / b + (a % b == 0 ? 0 : 1);
    }
}

File 14 of 16: Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "Context.sol";

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

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

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

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

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

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

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

File 15 of 16: SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 16 of 16: Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

Contract Security Audit

Contract ABI

[{"inputs":[],"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":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":[],"name":"License","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Provenance","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","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":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enforcerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flipPresale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flipPublicsale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxGenesisMonkes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTeamReserveMonkes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nounceTracker","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ogMaxMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ogPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"nounce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"presaleMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"publicMaxMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicSaleEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","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":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","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":"uint8","name":"amount","type":"uint8"},{"internalType":"address","name":"to","type":"address"}],"name":"teamReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"teamReserveCounter","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":"totalTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wlMaxMints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wlPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60006007556009805461ffff1916905560e0604052602f6080818152906200322f60a03980516200003991600a9160209091019062000127565b503480156200004757600080fd5b50604080518082018252600b81526a436f6f6c204d6f6e6b657360a81b602080830191825283518085019094526005845264434d4e4b5360d81b908401528151919291620000989160009162000127565b508051620000ae90600190602084019062000127565b505050620000cb620000c5620000d160201b60201c565b620000d5565b6200020a565b3390565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8280546200013590620001cd565b90600052602060002090601f016020900481019282620001595760008555620001a4565b82601f106200017457805160ff1916838001178555620001a4565b82800160010185558215620001a4579182015b82811115620001a457825182559160200191906001019062000187565b50620001b2929150620001b6565b5090565b5b80821115620001b25760008155600101620001b7565b600181811c90821680620001e257607f821691505b602082108114156200020457634e487b7160e01b600052602260045260246000fd5b50919050565b613015806200021a6000396000f3fe6080604052600436106102d05760003560e01c80637e1c0c0911610179578063c7c7f932116100d6578063d547cfb71161008a578063f2fde38b11610064578063f2fde38b14610764578063fe78dd0814610784578063ff39e707146107ac57600080fd5b8063d547cfb714610719578063e985e9c51461072e578063f10e040d1461074e57600080fd5b8063c87b56dd116100bb578063c87b56dd1461069d578063cf213163146106bd578063d043298b1461070657600080fd5b8063c7c7f93214610655578063c7f8d01a1461068257600080fd5b8063a22cb4651161012d578063a945bf8011610112578063a945bf80146105f7578063affe39c114610613578063b88d4fde1461063557600080fd5b8063a22cb465146105c2578063a8b80b93146105e257600080fd5b806391ba317a1161015e57806391ba317a1461058557806395d89b411461059a578063a0712d68146105af57600080fd5b80637e1c0c09146105525780638da5cb5b1461056757600080fd5b80632ab91bba1161023257806345947076116101e65780636b79638f116101c05780636b79638f1461050757806370a082311461051d578063715018a61461053d57600080fd5b806345947076146104b257806355f804b3146104c75780636352211e146104e757600080fd5b80633574f95b116102175780633574f95b1461045d5780633ccfd60b1461047d57806342842e0e1461049257600080fd5b80632ab91bba146104295780632fe8a9931461044857600080fd5b8063143b237f116102895780631dd18f471161026e5780631dd18f47146103de57806323326528146103f357806323b872dd1461040957600080fd5b8063143b237f1461039b57806315f5d8a0146103b557600080fd5b806306fdde03116102ba57806306fdde0314610321578063081812fc14610343578063095ea7b31461037b57600080fd5b8062acf348146102d557806301ffc9a7146102ec575b600080fd5b3480156102e157600080fd5b506102ea6107c1565b005b3480156102f857600080fd5b5061030c61030736600461296d565b610852565b60405190151581526020015b60405180910390f35b34801561032d57600080fd5b50610336610863565b6040516103189190612a00565b34801561034f57600080fd5b5061036361035e366004612a13565b6108f5565b6040516001600160a01b039091168152602001610318565b34801561038757600080fd5b506102ea610396366004612a48565b61098e565b3480156103a757600080fd5b5060095461030c9060ff1681565b3480156103c157600080fd5b506103d066b1a2bc2ec5000081565b604051908152602001610318565b3480156103ea57600080fd5b506103d0600481565b3480156103ff57600080fd5b506103d061271081565b34801561041557600080fd5b506102ea610424366004612a72565b610ac0565b34801561043557600080fd5b5060095461030c90610100900460ff1681565b34801561045457600080fd5b506103d0600381565b34801561046957600080fd5b506102ea610478366004612aae565b610b47565b34801561048957600080fd5b506102ea610cab565b34801561049e57600080fd5b506102ea6104ad366004612a72565b610df0565b3480156104be57600080fd5b506103d0600281565b3480156104d357600080fd5b506102ea6104e2366004612bac565b610e0b565b3480156104f357600080fd5b50610363610502366004612a13565b610e7c565b34801561051357600080fd5b506103d060075481565b34801561052957600080fd5b506103d0610538366004612bf5565b610f2a565b34801561054957600080fd5b506102ea611004565b34801561055e57600080fd5b506002546103d0565b34801561057357600080fd5b506006546001600160a01b0316610363565b34801561059157600080fd5b506103d061106a565b3480156105a657600080fd5b5061033661108e565b6102ea6105bd366004612a13565b61109d565b3480156105ce57600080fd5b506102ea6105dd366004612c10565b61123c565b3480156105ee57600080fd5b506102ea611247565b34801561060357600080fd5b506103d067011c37937e08000081565b34801561061f57600080fd5b506106286112db565b6040516103189190612c4c565b34801561064157600080fd5b506102ea610650366004612cb9565b611341565b34801561066157600080fd5b506103d0610670366004612bf5565b60086020526000908152604090205481565b34801561068e57600080fd5b506103d066d529ae9e86000081565b3480156106a957600080fd5b506103366106b8366004612a13565b6113cf565b3480156106c957600080fd5b506103366040518060400160405280600f81526020017f4d6f6e6b654c6963656e7365204343000000000000000000000000000000000081525081565b6102ea610714366004612d21565b6113da565b34801561072557600080fd5b506103366116b8565b34801561073a57600080fd5b5061030c610749366004612d63565b611746565b34801561075a57600080fd5b506103d061011381565b34801561077057600080fd5b506102ea61077f366004612bf5565b6117f2565b34801561079057600080fd5b5061036373d8a7fd1887cf690119ffed888924056af7f299ce81565b3480156107b857600080fd5b506103366118d1565b6006546001600160a01b031633146108205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b600061085d826118ed565b92915050565b60606000805461087290612d7f565b80601f016020809104026020016040519081016040528092919081815260200182805461089e90612d7f565b80156108eb5780601f106108c0576101008083540402835291602001916108eb565b820191906000526020600020905b8154815290600101906020018083116108ce57829003601f168201915b5050505050905090565b6000610900826119d0565b6109725760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e00000000000000000000000000000000000000006064820152608401610817565b506000908152600360205260409020546001600160a01b031690565b600061099982610e7c565b9050806001600160a01b0316836001600160a01b03161415610a235760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610817565b336001600160a01b0382161480610a3f5750610a3f8133611746565b610ab15760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610817565b610abb8383611a1a565b505050565b610aca3382611aa0565b610b3c5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610817565b610abb838383611b7b565b6006546001600160a01b03163314610ba15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b60025461271090610bb69060ff851690612e02565b1115610c045760405162461bcd60e51b815260206004820152601960248201527f436f6f6c204d6f6e6b65732061726520736f6c64206f757421000000000000006044820152606401610817565b6101138260ff16600754610c189190612e02565b1115610c665760405162461bcd60e51b815260206004820152601660248201527f5465616d207265736572766520636f6d706c65746564000000000000000000006044820152606401610817565b8160ff1660076000828254610c7b9190612e02565b90915550600090505b8260ff16811015610abb57610c9882611d16565b5080610ca381612e1a565b915050610c84565b6006546001600160a01b03163314610d055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b60004711610d555760405162461bcd60e51b815260206004820152601660248201527f4e6f2062616c616e636520746f207769746864726177000000000000000000006044820152606401610817565b604051600090339047908381818185875af1925050503d8060008114610d97576040519150601f19603f3d011682016040523d82523d6000602084013e610d9c565b606091505b5050905080610ded5760405162461bcd60e51b815260206004820152601a60248201527f5769746864726177207472616e73666572206661696c697572650000000000006044820152606401610817565b50565b610abb83838360405180602001604052806000815250611341565b6006546001600160a01b03163314610e655760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b8051610e7890600a9060208401906128a6565b5050565b6000610e87826119d0565b610ef95760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610817565b600060028381548110610f0e57610f0e612e53565b6000918252602090912001546001600160a01b03169392505050565b60006001600160a01b038216610fa85760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610817565b60025460005b81811015610ffd57836001600160a01b031660028281548110610fd357610fd3612e53565b6000918252602090912001546001600160a01b03161415610ff5578260010192505b600101610fae565b5050919050565b6006546001600160a01b0316331461105e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b6110686000611e07565b565b60025460009061107a5750600090565b60025461108990600190612e82565b905090565b60606001805461087290612d7f565b60095460ff6101009091041615156001146110fa5760405162461bcd60e51b815260206004820152601f60248201527f5075626c69632073616c65206973206e6f7420656e61626c65642079657421006044820152606401610817565b6002546127109061110c908390612e02565b111561115a5760405162461bcd60e51b815260206004820152601960248201527f436f6f6c204d6f6e6b65732061726520736f6c64206f757421000000000000006044820152606401610817565b60028111156111d15760405162461bcd60e51b815260206004820152602960248201527f546f6f206d75636820686f617264696e672c206d61782032207065722074726160448201527f6e73616374696f6e2100000000000000000000000000000000000000000000006064820152608401610817565b6111e367011c37937e08000082611e71565b3410156112325760405162461bcd60e51b815260206004820152601960248201527f496e636f727265637420616d6f756e74206f662066756e6473000000000000006044820152606401610817565b610ded8133611e84565b610e78338383612008565b6006546001600160a01b031633146112a15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff81166101009182900460ff1615909102179055565b60606000600280548060200260200160405190810160405280929190818152602001828054801561133557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611317575b50939695505050505050565b61134b3383611aa0565b6113bd5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610817565b6113c9848484846120f5565b50505050565b606061085d8261217e565b60095460ff1615156001146114315760405162461bcd60e51b815260206004820152601b60248201527f50726573616c65206973206e6f7420656e61626c6564207965742100000000006044820152606401610817565b60025461271090611443908690612e02565b11156114915760405162461bcd60e51b815260206004820152601960248201527f436f6f6c204d6f6e6b65732061726520736f6c64206f757421000000000000006044820152606401610817565b61149d60036004612e02565b336000908152600860205260409020546114bb90869060101c612e02565b11156115095760405162461bcd60e51b815260206004820152601560248201527f546f6f206d75636820686f617264696e67206d382100000000000000000000006044820152606401610817565b3360009081526008602052604090205461ffff168214156115925760405162461bcd60e51b815260206004820152602360248201527f43616e206e6f74207265706561742061207072696f72207472616e736163746960448201527f6f6e2100000000000000000000000000000000000000000000000000000000006064820152608401610817565b823410156115e25760405162461bcd60e51b815260206004820152601960248201527f496e636f727265637420616d6f756e74206f662066756e6473000000000000006044820152606401610817565b61160473d8a7fd1887cf690119ffed888924056af7f299ce33868686866122ec565b151560011461167b5760405162461bcd60e51b815260206004820152602760248201527f50726573616c65206d757374206265206d696e7465642066726f6d206f75722060448201527f77656273697465000000000000000000000000000000000000000000000000006064820152608401610817565b61168982601086901b612e02565b33600090815260086020526040812080549091906116a8908490612e02565b909155506113c990508433611e84565b600a80546116c590612d7f565b80601f01602080910402602001604051908101604052809291908181526020018280546116f190612d7f565b801561173e5780601f106117135761010080835404028352916020019161173e565b820191906000526020600020905b81548152906001019060200180831161172157829003601f168201915b505050505081565b600073a5409ec958c83c3f309868babaca7c86dcb077c16001600160a01b038316148061178f575073f42aa99f011a1fa7cda90e5e98b277e306bca83e6001600160a01b038316145b806117b65750734fee7b061c97c9c496b01dbce9cdb10c02f0a0be6001600160a01b038316145b156117c35750600161085d565b506001600160a01b03918216600090815260046020908152604080832093909416825291909152205460ff1690565b6006546001600160a01b0316331461184c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b6001600160a01b0381166118c85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610817565b610ded81611e07565b6040518060600160405280602a8152602001612fb6602a913981565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061198057507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061085d57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461085d565b6002546000908210801561085d575060006001600160a01b0316600283815481106119fd576119fd612e53565b6000918252602090912001546001600160a01b0316141592915050565b600081815260036020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384169081179091558190611a6782610e7c565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000611aab826119d0565b611b1d5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e00000000000000000000000000000000000000006064820152608401610817565b6000611b2883610e7c565b9050806001600160a01b0316846001600160a01b03161480611b635750836001600160a01b0316611b58846108f5565b6001600160a01b0316145b80611b735750611b738185611746565b949350505050565b826001600160a01b0316611b8e82610e7c565b6001600160a01b031614611c0a5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201527f73206e6f74206f776e00000000000000000000000000000000000000000000006064820152608401610817565b6001600160a01b038216611c855760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610817565b611c90600082611a1a565b8160028281548110611ca457611ca4612e53565b6000918252602082200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03938416179055604051839285811692908716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a4505050565b60006001600160a01b038216611d6e5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610817565b506002546002805460018101825560009182527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0385169081179091556040518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4919050565b600680546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000611e7d8284612e99565b9392505050565b60008211611ed45760405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420616d6f756e740000000000000000000000000000000000006044820152606401610817565b611ef8600082611ee384611d16565b604051806020016040528060008152506123c0565b611f6a5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610817565b6004821015611fa1578160021415611f8557610abb81611d16565b8160031415610e7857611f9781611d16565b50610abb81611d16565b6005821115611fed578160061415611fda57611fbc81611d16565b50611fc681611d16565b50611fd081611d16565b50611f9781611d16565b611fe381611d16565b50611fbc81611d16565b8160041415611fff57611fd081611d16565b611fc681611d16565b816001600160a01b0316836001600160a01b0316141561206a5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610817565b6001600160a01b0383811660008181526004602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b612100848484611b7b565b61210c848484846123c0565b6113c95760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610817565b6060612189826119d0565b6121fb5760405162461bcd60e51b815260206004820152603160248201527f45524337323155524953746f726167653a2055524920717565727920666f722060448201527f6e6f6e6578697374656e7420746f6b656e0000000000000000000000000000006064820152608401610817565b6000828152600560205260408120805461221490612d7f565b80601f016020809104026020016040519081016040528092919081815260200182805461224090612d7f565b801561228d5780601f106122625761010080835404028352916020019161228d565b820191906000526020600020905b81548152906001019060200180831161227057829003601f168201915b50505050509050600061229e61257c565b90508051600014156122b1575092915050565b8151156122e35780826040516020016122cb929190612ed6565b60405160208183030381529060405292505050919050565b611b738461258b565b604080517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660208083019190915260348201879052605482018690526074808301869052835180840390910181526094830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000060b484015260d08084018290528451808503909101815260f0909301909352815191012060009190886001600160a01b03166123a98286612663565b6001600160a01b0316149998505050505050505050565b60006001600160a01b0384163b15612571576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a029061241d903390899088908890600401612f05565b6020604051808303816000875af1925050508015612476575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261247391810190612f41565b60015b612526573d8080156124a4576040519150601f19603f3d011682016040523d82523d6000602084013e6124a9565b606091505b50805161251e5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610817565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050611b73565b506001949350505050565b6060600a805461087290612d7f565b6060612596826119d0565b6126085760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006064820152608401610817565b600061261261257c565b905060008151116126325760405180602001604052806000815250611e7d565b8061263c84612700565b60405160200161264d929190612ed6565b6040516020818303038152906040529392505050565b60008060008061267285612832565b6040805160008152602081018083528b905260ff8316918101919091526060810184905260808101839052929550909350915060019060a0016020604051602081039080840390855afa1580156126cd573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151979650505050505050565b60608161274057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561276a578061275481612e1a565b91506127639050600a83612f8d565b9150612744565b60008167ffffffffffffffff81111561278557612785612ae9565b6040519080825280601f01601f1916602001820160405280156127af576020820181803683370190505b5090505b8415611b73576127c4600183612e82565b91506127d1600a86612fa1565b6127dc906030612e02565b60f81b8183815181106127f1576127f1612e53565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061282b600a86612f8d565b94506127b3565b600080600083516041146128885760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964207369676e6174757265206c656e67746821000000000000006044820152606401610817565b50505060208101516040820151606090920151909260009190911a90565b8280546128b290612d7f565b90600052602060002090601f0160209004810192826128d4576000855561291a565b82601f106128ed57805160ff191683800117855561291a565b8280016001018555821561291a579182015b8281111561291a5782518255916020019190600101906128ff565b5061292692915061292a565b5090565b5b80821115612926576000815560010161292b565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114610ded57600080fd5b60006020828403121561297f57600080fd5b8135611e7d8161293f565b60005b838110156129a557818101518382015260200161298d565b838111156113c95750506000910152565b600081518084526129ce81602086016020860161298a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611e7d60208301846129b6565b600060208284031215612a2557600080fd5b5035919050565b80356001600160a01b0381168114612a4357600080fd5b919050565b60008060408385031215612a5b57600080fd5b612a6483612a2c565b946020939093013593505050565b600080600060608486031215612a8757600080fd5b612a9084612a2c565b9250612a9e60208501612a2c565b9150604084013590509250925092565b60008060408385031215612ac157600080fd5b823560ff81168114612ad257600080fd5b9150612ae060208401612a2c565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff80841115612b3357612b33612ae9565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612b7957612b79612ae9565b81604052809350858152868686011115612b9257600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215612bbe57600080fd5b813567ffffffffffffffff811115612bd557600080fd5b8201601f81018413612be657600080fd5b611b7384823560208401612b18565b600060208284031215612c0757600080fd5b611e7d82612a2c565b60008060408385031215612c2357600080fd5b612c2c83612a2c565b915060208301358015158114612c4157600080fd5b809150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015612c8d5783516001600160a01b031683529284019291840191600101612c68565b50909695505050505050565b600082601f830112612caa57600080fd5b611e7d83833560208501612b18565b60008060008060808587031215612ccf57600080fd5b612cd885612a2c565b9350612ce660208601612a2c565b925060408501359150606085013567ffffffffffffffff811115612d0957600080fd5b612d1587828801612c99565b91505092959194509250565b60008060008060808587031215612d3757600080fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115612d0957600080fd5b60008060408385031215612d7657600080fd5b612ad283612a2c565b600181811c90821680612d9357607f821691505b60208210811415612dcd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115612e1557612e15612dd3565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612e4c57612e4c612dd3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082821015612e9457612e94612dd3565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612ed157612ed1612dd3565b500290565b60008351612ee881846020880161298a565b835190830190612efc81836020880161298a565b01949350505050565b60006001600160a01b03808716835280861660208401525083604083015260806060830152612f3760808301846129b6565b9695505050505050565b600060208284031215612f5357600080fd5b8151611e7d8161293f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612f9c57612f9c612f5e565b500490565b600082612fb057612fb0612f5e565b50069056fe307835653963303636353633304338363539313830444131373963656634336564456134303135324433a264697066735822122082aa92ac4692e78bf23086d09a950f599f94f227180995a951eae1be4d86b04e64736f6c634300080b003368747470733a2f2f7777772e636f6f6c6d6f6e6b65732e696f2f6170692f6d657461646174612f67656e657369732f

Deployed Bytecode

0x6080604052600436106102d05760003560e01c80637e1c0c0911610179578063c7c7f932116100d6578063d547cfb71161008a578063f2fde38b11610064578063f2fde38b14610764578063fe78dd0814610784578063ff39e707146107ac57600080fd5b8063d547cfb714610719578063e985e9c51461072e578063f10e040d1461074e57600080fd5b8063c87b56dd116100bb578063c87b56dd1461069d578063cf213163146106bd578063d043298b1461070657600080fd5b8063c7c7f93214610655578063c7f8d01a1461068257600080fd5b8063a22cb4651161012d578063a945bf8011610112578063a945bf80146105f7578063affe39c114610613578063b88d4fde1461063557600080fd5b8063a22cb465146105c2578063a8b80b93146105e257600080fd5b806391ba317a1161015e57806391ba317a1461058557806395d89b411461059a578063a0712d68146105af57600080fd5b80637e1c0c09146105525780638da5cb5b1461056757600080fd5b80632ab91bba1161023257806345947076116101e65780636b79638f116101c05780636b79638f1461050757806370a082311461051d578063715018a61461053d57600080fd5b806345947076146104b257806355f804b3146104c75780636352211e146104e757600080fd5b80633574f95b116102175780633574f95b1461045d5780633ccfd60b1461047d57806342842e0e1461049257600080fd5b80632ab91bba146104295780632fe8a9931461044857600080fd5b8063143b237f116102895780631dd18f471161026e5780631dd18f47146103de57806323326528146103f357806323b872dd1461040957600080fd5b8063143b237f1461039b57806315f5d8a0146103b557600080fd5b806306fdde03116102ba57806306fdde0314610321578063081812fc14610343578063095ea7b31461037b57600080fd5b8062acf348146102d557806301ffc9a7146102ec575b600080fd5b3480156102e157600080fd5b506102ea6107c1565b005b3480156102f857600080fd5b5061030c61030736600461296d565b610852565b60405190151581526020015b60405180910390f35b34801561032d57600080fd5b50610336610863565b6040516103189190612a00565b34801561034f57600080fd5b5061036361035e366004612a13565b6108f5565b6040516001600160a01b039091168152602001610318565b34801561038757600080fd5b506102ea610396366004612a48565b61098e565b3480156103a757600080fd5b5060095461030c9060ff1681565b3480156103c157600080fd5b506103d066b1a2bc2ec5000081565b604051908152602001610318565b3480156103ea57600080fd5b506103d0600481565b3480156103ff57600080fd5b506103d061271081565b34801561041557600080fd5b506102ea610424366004612a72565b610ac0565b34801561043557600080fd5b5060095461030c90610100900460ff1681565b34801561045457600080fd5b506103d0600381565b34801561046957600080fd5b506102ea610478366004612aae565b610b47565b34801561048957600080fd5b506102ea610cab565b34801561049e57600080fd5b506102ea6104ad366004612a72565b610df0565b3480156104be57600080fd5b506103d0600281565b3480156104d357600080fd5b506102ea6104e2366004612bac565b610e0b565b3480156104f357600080fd5b50610363610502366004612a13565b610e7c565b34801561051357600080fd5b506103d060075481565b34801561052957600080fd5b506103d0610538366004612bf5565b610f2a565b34801561054957600080fd5b506102ea611004565b34801561055e57600080fd5b506002546103d0565b34801561057357600080fd5b506006546001600160a01b0316610363565b34801561059157600080fd5b506103d061106a565b3480156105a657600080fd5b5061033661108e565b6102ea6105bd366004612a13565b61109d565b3480156105ce57600080fd5b506102ea6105dd366004612c10565b61123c565b3480156105ee57600080fd5b506102ea611247565b34801561060357600080fd5b506103d067011c37937e08000081565b34801561061f57600080fd5b506106286112db565b6040516103189190612c4c565b34801561064157600080fd5b506102ea610650366004612cb9565b611341565b34801561066157600080fd5b506103d0610670366004612bf5565b60086020526000908152604090205481565b34801561068e57600080fd5b506103d066d529ae9e86000081565b3480156106a957600080fd5b506103366106b8366004612a13565b6113cf565b3480156106c957600080fd5b506103366040518060400160405280600f81526020017f4d6f6e6b654c6963656e7365204343000000000000000000000000000000000081525081565b6102ea610714366004612d21565b6113da565b34801561072557600080fd5b506103366116b8565b34801561073a57600080fd5b5061030c610749366004612d63565b611746565b34801561075a57600080fd5b506103d061011381565b34801561077057600080fd5b506102ea61077f366004612bf5565b6117f2565b34801561079057600080fd5b5061036373d8a7fd1887cf690119ffed888924056af7f299ce81565b3480156107b857600080fd5b506103366118d1565b6006546001600160a01b031633146108205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b600061085d826118ed565b92915050565b60606000805461087290612d7f565b80601f016020809104026020016040519081016040528092919081815260200182805461089e90612d7f565b80156108eb5780601f106108c0576101008083540402835291602001916108eb565b820191906000526020600020905b8154815290600101906020018083116108ce57829003601f168201915b5050505050905090565b6000610900826119d0565b6109725760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e00000000000000000000000000000000000000006064820152608401610817565b506000908152600360205260409020546001600160a01b031690565b600061099982610e7c565b9050806001600160a01b0316836001600160a01b03161415610a235760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610817565b336001600160a01b0382161480610a3f5750610a3f8133611746565b610ab15760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610817565b610abb8383611a1a565b505050565b610aca3382611aa0565b610b3c5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610817565b610abb838383611b7b565b6006546001600160a01b03163314610ba15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b60025461271090610bb69060ff851690612e02565b1115610c045760405162461bcd60e51b815260206004820152601960248201527f436f6f6c204d6f6e6b65732061726520736f6c64206f757421000000000000006044820152606401610817565b6101138260ff16600754610c189190612e02565b1115610c665760405162461bcd60e51b815260206004820152601660248201527f5465616d207265736572766520636f6d706c65746564000000000000000000006044820152606401610817565b8160ff1660076000828254610c7b9190612e02565b90915550600090505b8260ff16811015610abb57610c9882611d16565b5080610ca381612e1a565b915050610c84565b6006546001600160a01b03163314610d055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b60004711610d555760405162461bcd60e51b815260206004820152601660248201527f4e6f2062616c616e636520746f207769746864726177000000000000000000006044820152606401610817565b604051600090339047908381818185875af1925050503d8060008114610d97576040519150601f19603f3d011682016040523d82523d6000602084013e610d9c565b606091505b5050905080610ded5760405162461bcd60e51b815260206004820152601a60248201527f5769746864726177207472616e73666572206661696c697572650000000000006044820152606401610817565b50565b610abb83838360405180602001604052806000815250611341565b6006546001600160a01b03163314610e655760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b8051610e7890600a9060208401906128a6565b5050565b6000610e87826119d0565b610ef95760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610817565b600060028381548110610f0e57610f0e612e53565b6000918252602090912001546001600160a01b03169392505050565b60006001600160a01b038216610fa85760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610817565b60025460005b81811015610ffd57836001600160a01b031660028281548110610fd357610fd3612e53565b6000918252602090912001546001600160a01b03161415610ff5578260010192505b600101610fae565b5050919050565b6006546001600160a01b0316331461105e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b6110686000611e07565b565b60025460009061107a5750600090565b60025461108990600190612e82565b905090565b60606001805461087290612d7f565b60095460ff6101009091041615156001146110fa5760405162461bcd60e51b815260206004820152601f60248201527f5075626c69632073616c65206973206e6f7420656e61626c65642079657421006044820152606401610817565b6002546127109061110c908390612e02565b111561115a5760405162461bcd60e51b815260206004820152601960248201527f436f6f6c204d6f6e6b65732061726520736f6c64206f757421000000000000006044820152606401610817565b60028111156111d15760405162461bcd60e51b815260206004820152602960248201527f546f6f206d75636820686f617264696e672c206d61782032207065722074726160448201527f6e73616374696f6e2100000000000000000000000000000000000000000000006064820152608401610817565b6111e367011c37937e08000082611e71565b3410156112325760405162461bcd60e51b815260206004820152601960248201527f496e636f727265637420616d6f756e74206f662066756e6473000000000000006044820152606401610817565b610ded8133611e84565b610e78338383612008565b6006546001600160a01b031633146112a15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff81166101009182900460ff1615909102179055565b60606000600280548060200260200160405190810160405280929190818152602001828054801561133557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611317575b50939695505050505050565b61134b3383611aa0565b6113bd5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610817565b6113c9848484846120f5565b50505050565b606061085d8261217e565b60095460ff1615156001146114315760405162461bcd60e51b815260206004820152601b60248201527f50726573616c65206973206e6f7420656e61626c6564207965742100000000006044820152606401610817565b60025461271090611443908690612e02565b11156114915760405162461bcd60e51b815260206004820152601960248201527f436f6f6c204d6f6e6b65732061726520736f6c64206f757421000000000000006044820152606401610817565b61149d60036004612e02565b336000908152600860205260409020546114bb90869060101c612e02565b11156115095760405162461bcd60e51b815260206004820152601560248201527f546f6f206d75636820686f617264696e67206d382100000000000000000000006044820152606401610817565b3360009081526008602052604090205461ffff168214156115925760405162461bcd60e51b815260206004820152602360248201527f43616e206e6f74207265706561742061207072696f72207472616e736163746960448201527f6f6e2100000000000000000000000000000000000000000000000000000000006064820152608401610817565b823410156115e25760405162461bcd60e51b815260206004820152601960248201527f496e636f727265637420616d6f756e74206f662066756e6473000000000000006044820152606401610817565b61160473d8a7fd1887cf690119ffed888924056af7f299ce33868686866122ec565b151560011461167b5760405162461bcd60e51b815260206004820152602760248201527f50726573616c65206d757374206265206d696e7465642066726f6d206f75722060448201527f77656273697465000000000000000000000000000000000000000000000000006064820152608401610817565b61168982601086901b612e02565b33600090815260086020526040812080549091906116a8908490612e02565b909155506113c990508433611e84565b600a80546116c590612d7f565b80601f01602080910402602001604051908101604052809291908181526020018280546116f190612d7f565b801561173e5780601f106117135761010080835404028352916020019161173e565b820191906000526020600020905b81548152906001019060200180831161172157829003601f168201915b505050505081565b600073a5409ec958c83c3f309868babaca7c86dcb077c16001600160a01b038316148061178f575073f42aa99f011a1fa7cda90e5e98b277e306bca83e6001600160a01b038316145b806117b65750734fee7b061c97c9c496b01dbce9cdb10c02f0a0be6001600160a01b038316145b156117c35750600161085d565b506001600160a01b03918216600090815260046020908152604080832093909416825291909152205460ff1690565b6006546001600160a01b0316331461184c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b6001600160a01b0381166118c85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610817565b610ded81611e07565b6040518060600160405280602a8152602001612fb6602a913981565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061198057507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061085d57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461085d565b6002546000908210801561085d575060006001600160a01b0316600283815481106119fd576119fd612e53565b6000918252602090912001546001600160a01b0316141592915050565b600081815260036020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384169081179091558190611a6782610e7c565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000611aab826119d0565b611b1d5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e00000000000000000000000000000000000000006064820152608401610817565b6000611b2883610e7c565b9050806001600160a01b0316846001600160a01b03161480611b635750836001600160a01b0316611b58846108f5565b6001600160a01b0316145b80611b735750611b738185611746565b949350505050565b826001600160a01b0316611b8e82610e7c565b6001600160a01b031614611c0a5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201527f73206e6f74206f776e00000000000000000000000000000000000000000000006064820152608401610817565b6001600160a01b038216611c855760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610817565b611c90600082611a1a565b8160028281548110611ca457611ca4612e53565b6000918252602082200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03938416179055604051839285811692908716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a4505050565b60006001600160a01b038216611d6e5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610817565b506002546002805460018101825560009182527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0385169081179091556040518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4919050565b600680546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000611e7d8284612e99565b9392505050565b60008211611ed45760405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420616d6f756e740000000000000000000000000000000000006044820152606401610817565b611ef8600082611ee384611d16565b604051806020016040528060008152506123c0565b611f6a5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610817565b6004821015611fa1578160021415611f8557610abb81611d16565b8160031415610e7857611f9781611d16565b50610abb81611d16565b6005821115611fed578160061415611fda57611fbc81611d16565b50611fc681611d16565b50611fd081611d16565b50611f9781611d16565b611fe381611d16565b50611fbc81611d16565b8160041415611fff57611fd081611d16565b611fc681611d16565b816001600160a01b0316836001600160a01b0316141561206a5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610817565b6001600160a01b0383811660008181526004602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b612100848484611b7b565b61210c848484846123c0565b6113c95760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610817565b6060612189826119d0565b6121fb5760405162461bcd60e51b815260206004820152603160248201527f45524337323155524953746f726167653a2055524920717565727920666f722060448201527f6e6f6e6578697374656e7420746f6b656e0000000000000000000000000000006064820152608401610817565b6000828152600560205260408120805461221490612d7f565b80601f016020809104026020016040519081016040528092919081815260200182805461224090612d7f565b801561228d5780601f106122625761010080835404028352916020019161228d565b820191906000526020600020905b81548152906001019060200180831161227057829003601f168201915b50505050509050600061229e61257c565b90508051600014156122b1575092915050565b8151156122e35780826040516020016122cb929190612ed6565b60405160208183030381529060405292505050919050565b611b738461258b565b604080517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660208083019190915260348201879052605482018690526074808301869052835180840390910181526094830184528051908201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000060b484015260d08084018290528451808503909101815260f0909301909352815191012060009190886001600160a01b03166123a98286612663565b6001600160a01b0316149998505050505050505050565b60006001600160a01b0384163b15612571576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a029061241d903390899088908890600401612f05565b6020604051808303816000875af1925050508015612476575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261247391810190612f41565b60015b612526573d8080156124a4576040519150601f19603f3d011682016040523d82523d6000602084013e6124a9565b606091505b50805161251e5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610817565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050611b73565b506001949350505050565b6060600a805461087290612d7f565b6060612596826119d0565b6126085760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006064820152608401610817565b600061261261257c565b905060008151116126325760405180602001604052806000815250611e7d565b8061263c84612700565b60405160200161264d929190612ed6565b6040516020818303038152906040529392505050565b60008060008061267285612832565b6040805160008152602081018083528b905260ff8316918101919091526060810184905260808101839052929550909350915060019060a0016020604051602081039080840390855afa1580156126cd573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151979650505050505050565b60608161274057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561276a578061275481612e1a565b91506127639050600a83612f8d565b9150612744565b60008167ffffffffffffffff81111561278557612785612ae9565b6040519080825280601f01601f1916602001820160405280156127af576020820181803683370190505b5090505b8415611b73576127c4600183612e82565b91506127d1600a86612fa1565b6127dc906030612e02565b60f81b8183815181106127f1576127f1612e53565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061282b600a86612f8d565b94506127b3565b600080600083516041146128885760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964207369676e6174757265206c656e67746821000000000000006044820152606401610817565b50505060208101516040820151606090920151909260009190911a90565b8280546128b290612d7f565b90600052602060002090601f0160209004810192826128d4576000855561291a565b82601f106128ed57805160ff191683800117855561291a565b8280016001018555821561291a579182015b8281111561291a5782518255916020019190600101906128ff565b5061292692915061292a565b5090565b5b80821115612926576000815560010161292b565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114610ded57600080fd5b60006020828403121561297f57600080fd5b8135611e7d8161293f565b60005b838110156129a557818101518382015260200161298d565b838111156113c95750506000910152565b600081518084526129ce81602086016020860161298a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611e7d60208301846129b6565b600060208284031215612a2557600080fd5b5035919050565b80356001600160a01b0381168114612a4357600080fd5b919050565b60008060408385031215612a5b57600080fd5b612a6483612a2c565b946020939093013593505050565b600080600060608486031215612a8757600080fd5b612a9084612a2c565b9250612a9e60208501612a2c565b9150604084013590509250925092565b60008060408385031215612ac157600080fd5b823560ff81168114612ad257600080fd5b9150612ae060208401612a2c565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff80841115612b3357612b33612ae9565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612b7957612b79612ae9565b81604052809350858152868686011115612b9257600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215612bbe57600080fd5b813567ffffffffffffffff811115612bd557600080fd5b8201601f81018413612be657600080fd5b611b7384823560208401612b18565b600060208284031215612c0757600080fd5b611e7d82612a2c565b60008060408385031215612c2357600080fd5b612c2c83612a2c565b915060208301358015158114612c4157600080fd5b809150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015612c8d5783516001600160a01b031683529284019291840191600101612c68565b50909695505050505050565b600082601f830112612caa57600080fd5b611e7d83833560208501612b18565b60008060008060808587031215612ccf57600080fd5b612cd885612a2c565b9350612ce660208601612a2c565b925060408501359150606085013567ffffffffffffffff811115612d0957600080fd5b612d1587828801612c99565b91505092959194509250565b60008060008060808587031215612d3757600080fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115612d0957600080fd5b60008060408385031215612d7657600080fd5b612ad283612a2c565b600181811c90821680612d9357607f821691505b60208210811415612dcd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115612e1557612e15612dd3565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612e4c57612e4c612dd3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082821015612e9457612e94612dd3565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612ed157612ed1612dd3565b500290565b60008351612ee881846020880161298a565b835190830190612efc81836020880161298a565b01949350505050565b60006001600160a01b03808716835280861660208401525083604083015260806060830152612f3760808301846129b6565b9695505050505050565b600060208284031215612f5357600080fd5b8151611e7d8161293f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612f9c57612f9c612f5e565b500490565b600082612fb057612fb0612f5e565b50069056fe307835653963303636353633304338363539313830444131373963656634336564456134303135324433a264697066735822122082aa92ac4692e78bf23086d09a950f599f94f227180995a951eae1be4d86b04e64736f6c634300080b0033

Deployed Bytecode Sourcemap

2867:8045:12:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9955:91;;;;;;;;;;;;;:::i;:::-;;10756:153;;;;;;;;;;-1:-1:-1;10756:153:12;;;;;:::i;:::-;;:::i;:::-;;;611:14:16;;604:22;586:41;;574:2;559:18;10756:153:12;;;;;;;;3314:98:5;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;4825:217::-;;;;;;;;;;-1:-1:-1;4825:217:5;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1797:55:16;;;1779:74;;1767:2;1752:18;4825:217:5;1633:226:16;4363:401:5;;;;;;;;;;-1:-1:-1;4363:401:5;;;;;:::i;:::-;;:::i;4690:34:12:-;;;;;;;;;;-1:-1:-1;4690:34:12;;;;;;;;4361:44;;;;;;;;;;;;4395:10;4361:44;;;;;2470:25:16;;;2458:2;2443:18;4361:44:12;2324:177:16;4143:38:12;;;;;;;;;;;;4180:1;4143:38;;3846:48;;;;;;;;;;;;3889:5;3846:48;;5849:330:5;;;;;;;;;;-1:-1:-1;5849:330:5;;;;;:::i;:::-;;:::i;4731:37:12:-;;;;;;;;;;-1:-1:-1;4731:37:12;;;;;;;;;;;4188:38;;;;;;;;;;;;4225:1;4188:38;;9565:382;;;;;;;;;;-1:-1:-1;9565:382:12;;;;;:::i;:::-;;:::i;10162:252::-;;;;;;;;;;;;;:::i;6245:179:5:-;;;;;;;;;;-1:-1:-1;6245:179:5;;;;;:::i;:::-;;:::i;4234:42:12:-;;;;;;;;;;;;4275:1;4234:42;;5200:101;;;;;;;;;;-1:-1:-1;5200:101:12;;;;;:::i;:::-;;:::i;2563:232:5:-;;;;;;;;;;-1:-1:-1;2563:232:5;;;;;:::i;:::-;;:::i;4071:37:12:-;;;;;;;;;;;;;;;;2092:414:5;;;;;;;;;;-1:-1:-1;2092:414:5;;;;;:::i;:::-;;:::i;1659:101:13:-;;;;;;;;;;;;;:::i;5309:93:12:-;;;;;;;;;;-1:-1:-1;5380:7:12;:14;5309:93;;1027:85:13;;;;;;;;;;-1:-1:-1;1099:6:13;;-1:-1:-1;;;;;1099:6:13;1027:85;;3133:119:5;;;;;;;;;;;;;:::i;3476:102::-;;;;;;;;;;;;;:::i;6914:451:12:-;;;;;;:::i;:::-;;:::i;5109:153:5:-;;;;;;;;;;-1:-1:-1;5109:153:5;;;;;:::i;:::-;;:::i;10054:100:12:-;;;;;;;;;;;;;:::i;4463:48::-;;;;;;;;;;;;4501:10;4463:48;;2936:132:5;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;6490:320::-;;;;;;;;;;-1:-1:-1;6490:320:5;;;;;:::i;:::-;;:::i;4614:48:12:-;;;;;;;;;;-1:-1:-1;4614:48:12;;;;;:::i;:::-;;;;;;;;;;;;;;4412:44;;;;;;;;;;;;4446:10;4412:44;;10593:155;;;;;;;;;;-1:-1:-1;10593:155:12;;;;;:::i;:::-;;:::i;3567:50::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8747:810;;;;;;:::i;:::-;;:::i;4937:78::-;;;;;;;;;;;;;:::i;5328:459:5:-;;;;;;;;;;-1:-1:-1;5328:459:5;;;;;:::i;:::-;;:::i;4014:50:12:-;;;;;;;;;;;;4061:3;4014:50;;1909:198:13;;;;;;;;;;-1:-1:-1;1909:198:13;;;;;:::i;:::-;;:::i;3710:84:12:-;;;;;;;;;;;;3752:42;3710:84;;3624:79;;;;;;;;;;;;;:::i;9955:91::-;1099:6:13;;-1:-1:-1;;;;;1099:6:13;719:10:2;1239:23:13;1231:68;;;;-1:-1:-1;;;1231:68:13;;7745:2:16;1231:68:13;;;7727:21:16;;;7764:18;;;7757:30;7823:34;7803:18;;;7796:62;7875:18;;1231:68:13;;;;;;;;;10024:14:12::1;::::0;;10006:32;;::::1;10024:14;::::0;;::::1;10023:15;10006:32;::::0;;9955:91::o;10756:153::-;10841:4;10865:36;10889:11;10865:23;:36::i;:::-;10858:43;10756:153;-1:-1:-1;;10756:153:12:o;3314:98:5:-;3368:13;3400:5;3393:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3314:98;:::o;4825:217::-;4901:7;4928:16;4936:7;4928;:16::i;:::-;4920:73;;;;-1:-1:-1;;;4920:73:5;;8548:2:16;4920:73:5;;;8530:21:16;8587:2;8567:18;;;8560:30;8626:34;8606:18;;;8599:62;8697:14;8677:18;;;8670:42;8729:19;;4920:73:5;8346:408:16;4920:73:5;-1:-1:-1;5011:24:5;;;;:15;:24;;;;;;-1:-1:-1;;;;;5011:24:5;;4825:217::o;4363:401::-;4443:13;4459:23;4474:7;4459:14;:23::i;:::-;4443:39;;4506:5;-1:-1:-1;;;;;4500:11:5;:2;-1:-1:-1;;;;;4500:11:5;;;4492:57;;;;-1:-1:-1;;;4492:57:5;;8961:2:16;4492:57:5;;;8943:21:16;9000:2;8980:18;;;8973:30;9039:34;9019:18;;;9012:62;9110:3;9090:18;;;9083:31;9131:19;;4492:57:5;8759:397:16;4492:57:5;719:10:2;-1:-1:-1;;;;;4581:21:5;;;;:62;;-1:-1:-1;4606:37:5;4623:5;719:10:2;5328:459:5;:::i;4606:37::-;4560:165;;;;-1:-1:-1;;;4560:165:5;;9363:2:16;4560:165:5;;;9345:21:16;9402:2;9382:18;;;9375:30;9441:34;9421:18;;;9414:62;9512:26;9492:18;;;9485:54;9556:19;;4560:165:5;9161:420:16;4560:165:5;4736:21;4745:2;4749:7;4736:8;:21::i;:::-;4433:331;4363:401;;:::o;5849:330::-;6038:41;719:10:2;6071:7:5;6038:18;:41::i;:::-;6030:103;;;;-1:-1:-1;;;6030:103:5;;9788:2:16;6030:103:5;;;9770:21:16;9827:2;9807:18;;;9800:30;9866:34;9846:18;;;9839:62;9937:19;9917:18;;;9910:47;9974:19;;6030:103:5;9586:413:16;6030:103:5;6144:28;6154:4;6160:2;6164:7;6144:9;:28::i;9565:382:12:-;1099:6:13;;-1:-1:-1;;;;;1099:6:13;719:10:2;1239:23:13;1231:68;;;;-1:-1:-1;;;1231:68:13;;7745:2:16;1231:68:13;;;7727:21:16;;;7764:18;;;7757:30;7823:34;7803:18;;;7796:62;7875:18;;1231:68:13;7543:356:16;1231:68:13;9648:7:12::1;:14:::0;3889:5:::1;::::0;9648:23:::1;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;:43;;9640:81;;;::::0;-1:-1:-1;;;9640:81:12;;10528:2:16;9640:81:12::1;::::0;::::1;10510:21:16::0;10567:2;10547:18;;;10540:30;10606:27;10586:18;;;10579:55;10651:18;;9640:81:12::1;10326:349:16::0;9640:81:12::1;4061:3;9761:6;9740:27;;:18;;:27;;;;:::i;:::-;:51;;9732:86;;;::::0;-1:-1:-1;;;9732:86:12;;10882:2:16;9732:86:12::1;::::0;::::1;10864:21:16::0;10921:2;10901:18;;;10894:30;10960:24;10940:18;;;10933:52;11002:18;;9732:86:12::1;10680:346:16::0;9732:86:12::1;9851:6;9829:28;;:18;;:28;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;9872:9:12::1;::::0;-1:-1:-1;9868:72:12::1;9891:6;9887:10;;:1;:10;9868:72;;;9919:9;9925:2;9919:5;:9::i;:::-;-1:-1:-1::0;9899:3:12;::::1;::::0;::::1;:::i;:::-;;;;9868:72;;10162:252:::0;1099:6:13;;-1:-1:-1;;;;;1099:6:13;719:10:2;1239:23:13;1231:68;;;;-1:-1:-1;;;1231:68:13;;7745:2:16;1231:68:13;;;7727:21:16;;;7764:18;;;7757:30;7823:34;7803:18;;;7796:62;7875:18;;1231:68:13;7543:356:16;1231:68:13;10242:1:12::1;10218:21;:25;10210:60;;;::::0;-1:-1:-1;;;10210:60:12;;11433:2:16;10210:60:12::1;::::0;::::1;11415:21:16::0;11472:2;11452:18;;;11445:30;11511:24;11491:18;;;11484:52;11553:18;;10210:60:12::1;11231:346:16::0;10210:60:12::1;10300:49;::::0;10282:12:::1;::::0;10300:10:::1;::::0;10323:21:::1;::::0;10282:12;10300:49;10282:12;10300:49;10323:21;10300:10;:49:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10281:68;;;10368:7;10360:46;;;::::0;-1:-1:-1;;;10360:46:12;;11994:2:16;10360:46:12::1;::::0;::::1;11976:21:16::0;12033:2;12013:18;;;12006:30;12072:28;12052:18;;;12045:56;12118:18;;10360:46:12::1;11792:350:16::0;10360:46:12::1;10199:215;10162:252::o:0;6245:179:5:-;6378:39;6395:4;6401:2;6405:7;6378:39;;;;;;;;;;;;:16;:39::i;5200:101:12:-;1099:6:13;;-1:-1:-1;;;;;1099:6:13;719:10:2;1239:23:13;1231:68;;;;-1:-1:-1;;;1231:68:13;;7745:2:16;1231:68:13;;;7727:21:16;;;7764:18;;;7757:30;7823:34;7803:18;;;7796:62;7875:18;;1231:68:13;7543:356:16;1231:68:13;5271:22:12;;::::1;::::0;:12:::1;::::0;:22:::1;::::0;::::1;::::0;::::1;:::i;:::-;;5200:101:::0;:::o;2563:232:5:-;2635:7;2662:16;2670:7;2662;:16::i;:::-;2654:70;;;;-1:-1:-1;;;2654:70:5;;12349:2:16;2654:70:5;;;12331:21:16;12388:2;12368:18;;;12361:30;12427:34;12407:18;;;12400:62;12498:11;12478:18;;;12471:39;12527:19;;2654:70:5;12147:405:16;2654:70:5;2734:13;2750:7;2758;2750:16;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;2750:16:5;;2563:232;-1:-1:-1;;;2563:232:5:o;2092:414::-;2164:15;-1:-1:-1;;;;;2199:19:5;;2191:74;;;;-1:-1:-1;;;2191:74:5;;12948:2:16;2191:74:5;;;12930:21:16;12987:2;12967:18;;;12960:30;13026:34;13006:18;;;12999:62;13097:12;13077:18;;;13070:40;13127:19;;2191:74:5;12746:406:16;2191:74:5;2317:7;:14;2300;2345:144;2369:6;2365:1;:10;2345:144;;;2418:5;-1:-1:-1;;;;;2404:19:5;:7;2412:1;2404:10;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;2404:10:5;:19;2400:75;;;2447:9;;;;;2400:75;2377:3;;2345:144;;;;2276:223;2092:414;;;:::o;1659:101:13:-;1099:6;;-1:-1:-1;;;;;1099:6:13;719:10:2;1239:23:13;1231:68;;;;-1:-1:-1;;;1231:68:13;;7745:2:16;1231:68:13;;;7727:21:16;;;7764:18;;;7757:30;7823:34;7803:18;;;7796:62;7875:18;;1231:68:13;7543:356:16;1231:68:13;1723:30:::1;1750:1;1723:18;:30::i;:::-;1659:101::o:0;3133:119:5:-;3202:7;:14;3176:7;;3202:43;;-1:-1:-1;3244:1:5;;3133:119::o;3202:43::-;3223:7;:14;:18;;3240:1;;3223:18;:::i;:::-;3195:50;;3133:119;:::o;3476:102::-;3532:13;3564:7;3557:14;;;;;:::i;6914:451:12:-;6978:17;;;;;;;;:25;;:17;:25;6970:69;;;;-1:-1:-1;;;6970:69:12;;13489:2:16;6970:69:12;;;13471:21:16;13528:2;13508:18;;;13501:30;13567:33;13547:18;;;13540:61;13618:18;;6970:69:12;13287:355:16;6970:69:12;7058:7;:14;3889:5;;7058:23;;7075:6;;7058:23;:::i;:::-;:43;;7050:81;;;;-1:-1:-1;;;7050:81:12;;10528:2:16;7050:81:12;;;10510:21:16;10567:2;10547:18;;;10540:30;10606:27;10586:18;;;10579:55;10651:18;;7050:81:12;10326:349:16;7050:81:12;4275:1;7150:6;:24;;7142:78;;;;-1:-1:-1;;;7142:78:12;;13849:2:16;7142:78:12;;;13831:21:16;13888:2;13868:18;;;13861:30;13927:34;13907:18;;;13900:62;13998:11;13978:18;;;13971:39;14027:19;;7142:78:12;13647:405:16;7142:78:12;7252:23;4501:10;7268:6;7252:15;:23::i;:::-;7239:9;:36;;7231:74;;;;-1:-1:-1;;;7231:74:12;;14259:2:16;7231:74:12;;;14241:21:16;14298:2;14278:18;;;14271:30;14337:27;14317:18;;;14310:55;14382:18;;7231:74:12;14057:349:16;7231:74:12;7326:31;7336:6;719:10:2;7326:9:12;:31::i;5109:153:5:-;5203:52;719:10:2;5236:8:5;5246;5203:18;:52::i;10054:100:12:-;1099:6:13;;-1:-1:-1;;;;;1099:6:13;719:10:2;1239:23:13;1231:68;;;;-1:-1:-1;;;1231:68:13;;7745:2:16;1231:68:13;;;7727:21:16;;;7764:18;;;7757:30;7823:34;7803:18;;;7796:62;7875:18;;1231:68:13;7543:356:16;1231:68:13;10129:17:12::1;::::0;;10108:38;;::::1;10129:17;::::0;;;::::1;;;10128:18;10108:38:::0;;::::1;;::::0;;10054:100::o;2936:132:5:-;2975:16;3003:24;3030:7;3003:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3003:34:5;;;;;;;;;;;;;;;;-1:-1:-1;3003:34:5;;2936:132;-1:-1:-1;;;;;;2936:132:5:o;6490:320::-;6659:41;719:10:2;6692:7:5;6659:18;:41::i;:::-;6651:103;;;;-1:-1:-1;;;6651:103:5;;9788:2:16;6651:103:5;;;9770:21:16;9827:2;9807:18;;;9800:30;9866:34;9846:18;;;9839:62;9937:19;9917:18;;;9910:47;9974:19;;6651:103:5;9586:413:16;6651:103:5;6764:39;6778:4;6784:2;6788:7;6797:5;6764:13;:39::i;:::-;6490:320;;;;:::o;10593:155:12:-;10684:13;10717:23;10732:7;10717:14;:23::i;8747:810::-;8865:14;;;;:22;;:14;:22;8857:62;;;;-1:-1:-1;;;8857:62:12;;14613:2:16;8857:62:12;;;14595:21:16;14652:2;14632:18;;;14625:30;14691:29;14671:18;;;14664:57;14738:18;;8857:62:12;14411:351:16;8857:62:12;8938:7;:14;3889:5;;8938:23;;8955:6;;8938:23;:::i;:::-;:43;;8930:81;;;;-1:-1:-1;;;8930:81:12;;10528:2:16;8930:81:12;;;10510:21:16;10567:2;10547:18;;;10540:30;10606:27;10586:18;;;10579:55;10651:18;;8930:81:12;10326:349:16;8930:81:12;9078:23;4225:1;4180;9078:23;:::i;:::-;719:10:2;9031:27:12;;;;:13;:27;;;;;;9030:44;;9068:6;;9062:2;9031:33;9030:44;:::i;:::-;:71;;9022:105;;;;-1:-1:-1;;;9022:105:12;;14969:2:16;9022:105:12;;;14951:21:16;15008:2;14988:18;;;14981:30;15047:23;15027:18;;;15020:51;15088:18;;9022:105:12;14767:345:16;9022:105:12;719:10:2;9153:27:12;;;;:13;:27;;;;;;9146:45;;;;;9138:93;;;;-1:-1:-1;;;9138:93:12;;15319:2:16;9138:93:12;;;15301:21:16;15358:2;15338:18;;;15331:30;15397:34;15377:18;;;15370:62;15468:5;15448:18;;;15441:33;15491:19;;9138:93:12;15117:399:16;9138:93:12;9263:5;9250:9;:18;;9242:56;;;;-1:-1:-1;;;9242:56:12;;14259:2:16;9242:56:12;;;14241:21:16;14298:2;14278:18;;;14271:30;14337:27;14317:18;;;14310:55;14382:18;;9242:56:12;14057:349:16;9242:56:12;9317:71;3752:42;719:10:2;9355:6:12;9363:5;9370:6;9378:9;9317:6;:71::i;:::-;:79;;9392:4;9317:79;9309:131;;;;-1:-1:-1;;;9309:131:12;;15723:2:16;9309:131:12;;;15705:21:16;15762:2;15742:18;;;15735:30;15801:34;15781:18;;;15774:62;15872:9;15852:18;;;15845:37;15899:19;;9309:131:12;15521:403:16;9309:131:12;9484:23;9501:6;9495:2;9485:12;;;9484:23;:::i;:::-;719:10:2;9453:27:12;;;;:13;:27;;;;;:54;;:27;;;:54;;;;;:::i;:::-;;;;-1:-1:-1;9518:31:12;;-1:-1:-1;9528:6:12;719:10:2;7326:9:12;:31::i;4937:78::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5328:459:5:-;5425:4;5512:42;-1:-1:-1;;;;;5500:54:5;;;;:112;;-1:-1:-1;5570:42:5;-1:-1:-1;;;;;5558:54:5;;;5500:112;:170;;;-1:-1:-1;5628:42:5;-1:-1:-1;;;;;5616:54:5;;;5500:170;5496:285;;;-1:-1:-1;5693:4:5;5686:11;;5496:285;-1:-1:-1;;;;;;5735:25:5;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;5328:459::o;1909:198:13:-;1099:6;;-1:-1:-1;;;;;1099:6:13;719:10:2;1239:23:13;1231:68;;;;-1:-1:-1;;;1231:68:13;;7745:2:16;1231:68:13;;;7727:21:16;;;7764:18;;;7757:30;7823:34;7803:18;;;7796:62;7875:18;;1231:68:13;7543:356:16;1231:68:13;-1:-1:-1;;;;;1997:22:13;::::1;1989:73;;;::::0;-1:-1:-1;;;1989:73:13;;16131:2:16;1989:73:13::1;::::0;::::1;16113:21:16::0;16170:2;16150:18;;;16143:30;16209:34;16189:18;;;16182:62;16280:8;16260:18;;;16253:36;16306:19;;1989:73:13::1;15929:402:16::0;1989:73:13::1;2072:28;2091:8;2072:18;:28::i;3624:79:12:-:0;;;;;;;;;;;;;;;;;;;:::o;1733:300:5:-;1835:4;1870:40;;;1885:25;1870:40;;:104;;-1:-1:-1;1926:48:5;;;1941:33;1926:48;1870:104;:156;;;-1:-1:-1;950:25:4;935:40;;;;1990:36:5;827:155:4;8282:153:5;8380:7;:14;8347:4;;8370:24;;:58;;;;;8426:1;-1:-1:-1;;;;;8398:30:5;:7;8406;8398:16;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;8398:16:5;:30;;8363:65;8282:153;-1:-1:-1;;8282:153:5:o;11493:171::-;11567:24;;;;:15;:24;;;;;:29;;;;-1:-1:-1;;;;;11567:29:5;;;;;;;;:24;;11620:23;11567:24;11620:14;:23::i;:::-;-1:-1:-1;;;;;11611:46:5;;;;;;;;;;;11493:171;;:::o;8593:344::-;8686:4;8710:16;8718:7;8710;:16::i;:::-;8702:73;;;;-1:-1:-1;;;8702:73:5;;16538:2:16;8702:73:5;;;16520:21:16;16577:2;16557:18;;;16550:30;16616:34;16596:18;;;16589:62;16687:14;16667:18;;;16660:42;16719:19;;8702:73:5;16336:408:16;8702:73:5;8785:13;8801:23;8816:7;8801:14;:23::i;:::-;8785:39;;8853:5;-1:-1:-1;;;;;8842:16:5;:7;-1:-1:-1;;;;;8842:16:5;;:51;;;;8886:7;-1:-1:-1;;;;;8862:31:5;:20;8874:7;8862:11;:20::i;:::-;-1:-1:-1;;;;;8862:31:5;;8842:51;:87;;;;8897:32;8914:5;8921:7;8897:16;:32::i;:::-;8834:96;8593:344;-1:-1:-1;;;;8593:344:5:o;10880:502::-;11034:4;-1:-1:-1;;;;;11007:31:5;:23;11022:7;11007:14;:23::i;:::-;-1:-1:-1;;;;;11007:31:5;;10999:85;;;;-1:-1:-1;;;10999:85:5;;16951:2:16;10999:85:5;;;16933:21:16;16990:2;16970:18;;;16963:30;17029:34;17009:18;;;17002:62;17100:11;17080:18;;;17073:39;17129:19;;10999:85:5;16749:405:16;10999:85:5;-1:-1:-1;;;;;11102:16:5;;11094:65;;;;-1:-1:-1;;;11094:65:5;;17361:2:16;11094:65:5;;;17343:21:16;17400:2;17380:18;;;17373:30;17439:34;17419:18;;;17412:62;17510:6;17490:18;;;17483:34;17534:19;;11094:65:5;17159:400:16;11094:65:5;11271:29;11288:1;11292:7;11271:8;:29::i;:::-;11330:2;11311:7;11319;11311:16;;;;;;;;:::i;:::-;;;;;;;;;:21;;;;-1:-1:-1;;;;;11311:21:5;;;;;;11348:27;;11367:7;;11348:27;;;;;;;;;;11311:16;11348:27;10880:502;;;:::o;10241:314::-;10294:15;-1:-1:-1;;;;;10329:16:5;;10321:61;;;;-1:-1:-1;;;10321:61:5;;17766:2:16;10321:61:5;;;17748:21:16;;;17785:18;;;17778:30;17844:34;17824:18;;;17817:62;17896:18;;10321:61:5;17564:356:16;10321:61:5;-1:-1:-1;10402:7:5;:14;10483:7;:16;;;;;;;-1:-1:-1;10483:16:5;;;;;;;;;-1:-1:-1;;;;;10483:16:5;;;;;;;;10515:33;;10540:7;;-1:-1:-1;10515:33:5;;-1:-1:-1;;10515:33:5;10241:314;;;:::o;2261:187:13:-;2353:6;;;-1:-1:-1;;;;;2369:17:13;;;;;;;;;;;2401:40;;2353:6;;;2369:17;2353:6;;2401:40;;2334:16;;2401:40;2324:124;2261:187;:::o;3451:96:14:-;3509:7;3535:5;3539:1;3535;:5;:::i;:::-;3528:12;3451:96;-1:-1:-1;;;3451:96:14:o;5575:1331:12:-;5655:1;5646:6;:10;5638:37;;;;-1:-1:-1;;;5638:37:12;;18360:2:16;5638:37:12;;;18342:21:16;18399:2;18379:18;;;18372:30;18438:16;18418:18;;;18411:44;18472:18;;5638:37:12;18158:338:16;5638:37:12;5694:53;5725:1;5729:2;5733:9;5739:2;5733:5;:9::i;:::-;5694:53;;;;;;;;;;;;:22;:53::i;:::-;5686:116;;;;-1:-1:-1;;;5686:116:12;;18703:2:16;5686:116:12;;;18685:21:16;18742:2;18722:18;;;18715:30;18781:34;18761:18;;;18754:62;18852:20;18832:18;;;18825:48;18890:19;;5686:116:12;18501:414:16;5686:116:12;5878:1;5869:6;:10;5865:1032;;;5900:6;5910:1;5900:11;5896:156;;;5932:9;5938:2;5932:5;:9::i;5896:156::-;5967:6;5977:1;5967:11;5963:89;;;5999:9;6005:2;5999:5;:9::i;:::-;;6027;6033:2;6027:5;:9::i;5865:1032::-;6097:1;6088:6;:10;6084:802;;;6123:6;6133:1;6123:11;6119:420;;;6159:9;6165:2;6159:5;:9::i;:::-;;6191;6197:2;6191:5;:9::i;:::-;;6223;6229:2;6223:5;:9::i;:::-;;6255;6261:2;6255:5;:9::i;6119:420::-;6350:9;6356:2;6350:5;:9::i;:::-;;6382;6388:2;6382:5;:9::i;6084:802::-;6583:6;6593:1;6583:11;6579:292;;;6619:9;6625:2;6619:5;:9::i;6579:292::-;6746:9;6752:2;6746:5;:9::i;11799:307:5:-;11949:8;-1:-1:-1;;;;;11940:17:5;:5;-1:-1:-1;;;;;11940:17:5;;;11932:55;;;;-1:-1:-1;;;11932:55:5;;19122:2:16;11932:55:5;;;19104:21:16;19161:2;19141:18;;;19134:30;19200:27;19180:18;;;19173:55;19245:18;;11932:55:5;18920:349:16;11932:55:5;-1:-1:-1;;;;;11997:25:5;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;;;;;;;;;;;;12058:41;;586::16;;;12058::5;;559:18:16;12058:41:5;;;;;;;11799:307;;;:::o;7672:::-;7823:28;7833:4;7839:2;7843:7;7823:9;:28::i;:::-;7869:48;7892:4;7898:2;7902:7;7911:5;7869:22;:48::i;:::-;7861:111;;;;-1:-1:-1;;;7861:111:5;;18703:2:16;7861:111:5;;;18685:21:16;18742:2;18722:18;;;18715:30;18781:34;18761:18;;;18754:62;18852:20;18832:18;;;18825:48;18890:19;;7861:111:5;18501:414:16;464:663:6;537:13;570:16;578:7;570;:16::i;:::-;562:78;;;;-1:-1:-1;;;562:78:6;;19476:2:16;562:78:6;;;19458:21:16;19515:2;19495:18;;;19488:30;19554:34;19534:18;;;19527:62;19625:19;19605:18;;;19598:47;19662:19;;562:78:6;19274:413:16;562:78:6;651:23;677:19;;;:10;:19;;;;;651:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;706:18;727:10;:8;:10::i;:::-;706:31;;816:4;810:18;832:1;810:23;806:70;;;-1:-1:-1;856:9:6;464:663;-1:-1:-1;;464:663:6:o;806:70::-;978:23;;:27;974:106;;1052:4;1058:9;1035:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;1021:48;;;;464:663;;;:::o;974:106::-;1097:23;1112:7;1097:14;:23::i;7771:379:12:-;7510:46;;;21600:66:16;21587:2;21583:15;;;21579:88;7510:46:12;;;;21567:101:16;;;;21684:12;;;21677:28;;;21721:12;;;21714:28;;;21758:12;;;;21751:28;;;7510:46:12;;;;;;;;;;21795:13:16;;;7510:46:12;;7500:57;;;;;;22061:66:16;7688::12;;;22049:79:16;22144:12;;;;22137:28;;;7688:66:12;;;;;;;;;;22181:12:16;;;;7688:66:12;;;7678:77;;;;;-1:-1:-1;;7500:57:12;8135:7;-1:-1:-1;;;;;8085:57:12;:46;8099:20;8121:9;8085:13;:46::i;:::-;-1:-1:-1;;;;;8085:57:12;;;7771:379;-1:-1:-1;;;;;;;;;7771:379:12:o;12659:779:5:-;12810:4;-1:-1:-1;;;;;12830:13:5;;1087:20:0;1133:8;12826:606:5;;12865:72;;;;;-1:-1:-1;;;;;12865:36:5;;;;;:72;;719:10:2;;12916:4:5;;12922:7;;12931:5;;12865:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12865:72:5;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;12861:519;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;13104:13:5;;13100:266;;13146:60;;-1:-1:-1;;;13146:60:5;;18703:2:16;13146:60:5;;;18685:21:16;18742:2;18722:18;;;18715:30;18781:34;18761:18;;;18754:62;18852:20;18832:18;;;18825:48;18890:19;;13146:60:5;18501:414:16;13100:266:5;13318:6;13312:13;13303:6;13299:2;13295:15;13288:38;12861:519;12987:51;;12997:41;12987:51;;-1:-1:-1;12980:58:5;;12826:606;-1:-1:-1;13417:4:5;12659:779;;;;;;:::o;5079:113:12:-;5139:13;5172:12;5165:19;;;;;:::i;3644:329:5:-;3717:13;3750:16;3758:7;3750;:16::i;:::-;3742:76;;;;-1:-1:-1;;;3742:76:5;;21140:2:16;3742:76:5;;;21122:21:16;21179:2;21159:18;;;21152:30;21218:34;21198:18;;;21191:62;21289:17;21269:18;;;21262:45;21324:19;;3742:76:5;20938:411:16;3742:76:5;3829:21;3853:10;:8;:10::i;:::-;3829:34;;3904:1;3886:7;3880:21;:25;:86;;;;;;;;;;;;;;;;;3932:7;3941:18;:7;:16;:18::i;:::-;3915:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;3873:93;3644:329;-1:-1:-1;;;3644:329:5:o;8158:249:12:-;8260:7;8281:9;8292;8303:7;8314:26;8329:10;8314:14;:26::i;:::-;8358:41;;;;;;;;;;;;22431:25:16;;;22504:4;22492:17;;22472:18;;;22465:45;;;;22526:18;;;22519:34;;;22569:18;;;22562:34;;;8280:60:12;;-1:-1:-1;8280:60:12;;-1:-1:-1;8280:60:12;-1:-1:-1;8358:41:12;;22403:19:16;;8358:41:12;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8358:41:12;;;;;;8158:249;-1:-1:-1;;;;;;;8158:249:12:o;328:703:15:-;384:13;601:10;597:51;;-1:-1:-1;;627:10:15;;;;;;;;;;;;;;;;;;328:703::o;597:51::-;672:5;657:12;711:75;718:9;;711:75;;743:8;;;;:::i;:::-;;-1:-1:-1;765:10:15;;-1:-1:-1;773:2:15;765:10;;:::i;:::-;;;711:75;;;795:19;827:6;817:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;817:17:15;;795:39;;844:150;851:10;;844:150;;877:11;887:1;877:11;;:::i;:::-;;-1:-1:-1;945:10:15;953:2;945:5;:10;:::i;:::-;932:24;;:2;:24;:::i;:::-;919:39;;902:6;909;902:14;;;;;;;;:::i;:::-;;;;:56;;;;;;;;;;-1:-1:-1;972:11:15;981:2;972:11;;:::i;:::-;;;844:150;;8415:324:12;8480:9;8491;8502:7;8531:3;:10;8545:2;8531:16;8523:54;;;;-1:-1:-1;;;8523:54:12;;23240:2:16;8523:54:12;;;23222:21:16;23279:2;23259:18;;;23252:30;23318:27;23298:18;;;23291:55;23363:18;;8523:54:12;23038:349:16;8523:54:12;-1:-1:-1;;;8632:2:12;8623:12;;8617:19;8670:2;8661:12;;8655:19;8716:2;8707:12;;;8701:19;8617;;8698:1;8693:28;;;;;8415:324::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:177:16;99:66;92:5;88:78;81:5;78:89;68:117;;181:1;178;171:12;196:245;254:6;307:2;295:9;286:7;282:23;278:32;275:52;;;323:1;320;313:12;275:52;362:9;349:23;381:30;405:5;381:30;:::i;638:258::-;710:1;720:113;734:6;731:1;728:13;720:113;;;810:11;;;804:18;791:11;;;784:39;756:2;749:10;720:113;;;851:6;848:1;845:13;842:48;;;-1:-1:-1;;886:1:16;868:16;;861:27;638:258::o;901:317::-;943:3;981:5;975:12;1008:6;1003:3;996:19;1024:63;1080:6;1073:4;1068:3;1064:14;1057:4;1050:5;1046:16;1024:63;:::i;:::-;1132:2;1120:15;1137:66;1116:88;1107:98;;;;1207:4;1103:109;;901:317;-1:-1:-1;;901:317:16:o;1223:220::-;1372:2;1361:9;1354:21;1335:4;1392:45;1433:2;1422:9;1418:18;1410:6;1392:45;:::i;1448:180::-;1507:6;1560:2;1548:9;1539:7;1535:23;1531:32;1528:52;;;1576:1;1573;1566:12;1528:52;-1:-1:-1;1599:23:16;;1448:180;-1:-1:-1;1448:180:16:o;1864:196::-;1932:20;;-1:-1:-1;;;;;1981:54:16;;1971:65;;1961:93;;2050:1;2047;2040:12;1961:93;1864:196;;;:::o;2065:254::-;2133:6;2141;2194:2;2182:9;2173:7;2169:23;2165:32;2162:52;;;2210:1;2207;2200:12;2162:52;2233:29;2252:9;2233:29;:::i;:::-;2223:39;2309:2;2294:18;;;;2281:32;;-1:-1:-1;;;2065:254:16:o;2506:328::-;2583:6;2591;2599;2652:2;2640:9;2631:7;2627:23;2623:32;2620:52;;;2668:1;2665;2658:12;2620:52;2691:29;2710:9;2691:29;:::i;:::-;2681:39;;2739:38;2773:2;2762:9;2758:18;2739:38;:::i;:::-;2729:48;;2824:2;2813:9;2809:18;2796:32;2786:42;;2506:328;;;;;:::o;2839:343::-;2905:6;2913;2966:2;2954:9;2945:7;2941:23;2937:32;2934:52;;;2982:1;2979;2972:12;2934:52;3021:9;3008:23;3071:4;3064:5;3060:16;3053:5;3050:27;3040:55;;3091:1;3088;3081:12;3040:55;3114:5;-1:-1:-1;3138:38:16;3172:2;3157:18;;3138:38;:::i;:::-;3128:48;;2839:343;;;;;:::o;3187:184::-;3239:77;3236:1;3229:88;3336:4;3333:1;3326:15;3360:4;3357:1;3350:15;3376:691;3441:5;3471:18;3512:2;3504:6;3501:14;3498:40;;;3518:18;;:::i;:::-;3652:2;3646:9;3718:2;3706:15;;3557:66;3702:24;;;3728:2;3698:33;3694:42;3682:55;;;3752:18;;;3772:22;;;3749:46;3746:72;;;3798:18;;:::i;:::-;3838:10;3834:2;3827:22;3867:6;3858:15;;3897:6;3889;3882:22;3937:3;3928:6;3923:3;3919:16;3916:25;3913:45;;;3954:1;3951;3944:12;3913:45;4004:6;3999:3;3992:4;3984:6;3980:17;3967:44;4059:1;4052:4;4043:6;4035;4031:19;4027:30;4020:41;;;;3376:691;;;;;:::o;4072:451::-;4141:6;4194:2;4182:9;4173:7;4169:23;4165:32;4162:52;;;4210:1;4207;4200:12;4162:52;4250:9;4237:23;4283:18;4275:6;4272:30;4269:50;;;4315:1;4312;4305:12;4269:50;4338:22;;4391:4;4383:13;;4379:27;-1:-1:-1;4369:55:16;;4420:1;4417;4410:12;4369:55;4443:74;4509:7;4504:2;4491:16;4486:2;4482;4478:11;4443:74;:::i;4528:186::-;4587:6;4640:2;4628:9;4619:7;4615:23;4611:32;4608:52;;;4656:1;4653;4646:12;4608:52;4679:29;4698:9;4679:29;:::i;4719:347::-;4784:6;4792;4845:2;4833:9;4824:7;4820:23;4816:32;4813:52;;;4861:1;4858;4851:12;4813:52;4884:29;4903:9;4884:29;:::i;:::-;4874:39;;4963:2;4952:9;4948:18;4935:32;5010:5;5003:13;4996:21;4989:5;4986:32;4976:60;;5032:1;5029;5022:12;4976:60;5055:5;5045:15;;;4719:347;;;;;:::o;5071:681::-;5242:2;5294:21;;;5364:13;;5267:18;;;5386:22;;;5213:4;;5242:2;5465:15;;;;5439:2;5424:18;;;5213:4;5508:218;5522:6;5519:1;5516:13;5508:218;;;5587:13;;-1:-1:-1;;;;;5583:62:16;5571:75;;5701:15;;;;5666:12;;;;5544:1;5537:9;5508:218;;;-1:-1:-1;5743:3:16;;5071:681;-1:-1:-1;;;;;;5071:681:16:o;5757:221::-;5799:5;5852:3;5845:4;5837:6;5833:17;5829:27;5819:55;;5870:1;5867;5860:12;5819:55;5892:80;5968:3;5959:6;5946:20;5939:4;5931:6;5927:17;5892:80;:::i;5983:537::-;6078:6;6086;6094;6102;6155:3;6143:9;6134:7;6130:23;6126:33;6123:53;;;6172:1;6169;6162:12;6123:53;6195:29;6214:9;6195:29;:::i;:::-;6185:39;;6243:38;6277:2;6266:9;6262:18;6243:38;:::i;:::-;6233:48;;6328:2;6317:9;6313:18;6300:32;6290:42;;6383:2;6372:9;6368:18;6355:32;6410:18;6402:6;6399:30;6396:50;;;6442:1;6439;6432:12;6396:50;6465:49;6506:7;6497:6;6486:9;6482:22;6465:49;:::i;:::-;6455:59;;;5983:537;;;;;;;:::o;6525:525::-;6620:6;6628;6636;6644;6697:3;6685:9;6676:7;6672:23;6668:33;6665:53;;;6714:1;6711;6704:12;6665:53;6750:9;6737:23;6727:33;;6807:2;6796:9;6792:18;6779:32;6769:42;;6858:2;6847:9;6843:18;6830:32;6820:42;;6913:2;6902:9;6898:18;6885:32;6940:18;6932:6;6929:30;6926:50;;;6972:1;6969;6962:12;7055:260;7123:6;7131;7184:2;7172:9;7163:7;7159:23;7155:32;7152:52;;;7200:1;7197;7190:12;7152:52;7223:29;7242:9;7223:29;:::i;7904:437::-;7983:1;7979:12;;;;8026;;;8047:61;;8101:4;8093:6;8089:17;8079:27;;8047:61;8154:2;8146:6;8143:14;8123:18;8120:38;8117:218;;;8191:77;8188:1;8181:88;8292:4;8289:1;8282:15;8320:4;8317:1;8310:15;8117:218;;7904:437;;;:::o;10004:184::-;10056:77;10053:1;10046:88;10153:4;10150:1;10143:15;10177:4;10174:1;10167:15;10193:128;10233:3;10264:1;10260:6;10257:1;10254:13;10251:39;;;10270:18;;:::i;:::-;-1:-1:-1;10306:9:16;;10193:128::o;11031:195::-;11070:3;11101:66;11094:5;11091:77;11088:103;;;11171:18;;:::i;:::-;-1:-1:-1;11218:1:16;11207:13;;11031:195::o;12557:184::-;12609:77;12606:1;12599:88;12706:4;12703:1;12696:15;12730:4;12727:1;12720:15;13157:125;13197:4;13225:1;13222;13219:8;13216:34;;;13230:18;;:::i;:::-;-1:-1:-1;13267:9:16;;13157:125::o;17925:228::-;17965:7;18091:1;18023:66;18019:74;18016:1;18013:81;18008:1;18001:9;17994:17;17990:105;17987:131;;;18098:18;;:::i;:::-;-1:-1:-1;18138:9:16;;17925:228::o;19692:470::-;19871:3;19909:6;19903:13;19925:53;19971:6;19966:3;19959:4;19951:6;19947:17;19925:53;:::i;:::-;20041:13;;20000:16;;;;20063:57;20041:13;20000:16;20097:4;20085:17;;20063:57;:::i;:::-;20136:20;;19692:470;-1:-1:-1;;;;19692:470:16:o;20167:512::-;20361:4;-1:-1:-1;;;;;20471:2:16;20463:6;20459:15;20448:9;20441:34;20523:2;20515:6;20511:15;20506:2;20495:9;20491:18;20484:43;;20563:6;20558:2;20547:9;20543:18;20536:34;20606:3;20601:2;20590:9;20586:18;20579:31;20627:46;20668:3;20657:9;20653:19;20645:6;20627:46;:::i;:::-;20619:54;20167:512;-1:-1:-1;;;;;;20167:512:16:o;20684:249::-;20753:6;20806:2;20794:9;20785:7;20781:23;20777:32;20774:52;;;20822:1;20819;20812:12;20774:52;20854:9;20848:16;20873:30;20897:5;20873:30;:::i;22607:184::-;22659:77;22656:1;22649:88;22756:4;22753:1;22746:15;22780:4;22777:1;22770:15;22796:120;22836:1;22862;22852:35;;22867:18;;:::i;:::-;-1:-1:-1;22901:9:16;;22796:120::o;22921:112::-;22953:1;22979;22969:35;;22984:18;;:::i;:::-;-1:-1:-1;23018:9:16;;22921:112::o

Swarm Source

ipfs://82aa92ac4692e78bf23086d09a950f599f94f227180995a951eae1be4d86b04e
Loading...
Loading
Loading...
Loading
[ 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.