ETH Price: $3,437.15 (-1.46%)
Gas: 9 Gwei

Token

BitKoi (BITKOI)
 

Overview

Max Total Supply

18 BITKOI

Holders

9

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
0xtruls.eth
Balance
1 BITKOI
0xaf442257d853a2cbe6f266f6637fdce1a56a629c
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
BitKoiCore

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-10-15
*/

// File: contracts/common/Initializable.sol



pragma solidity ^0.8.0;

contract Initializable {
    bool inited = false;

    modifier initializer() {
        require(!inited, "already inited");
        _;
        inited = true;
    }
}

// File: contracts/common/EIP712Base.sol



pragma solidity ^0.8.0;


contract EIP712Base is Initializable {
    struct EIP712Domain {
        string name;
        string version;
        address verifyingContract;
        bytes32 salt;
    }

    string constant public ERC712_VERSION = "1";

    bytes32 internal constant EIP712_DOMAIN_TYPEHASH = keccak256(
        bytes(
            "EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)"
        )
    );
    bytes32 internal domainSeperator;

    // supposed to be called once while initializing.
    // one of the contracts that inherits this contract follows proxy pattern
    // so it is not possible to do this in a constructor
    function _initializeEIP712(
        string memory name
    )
        internal
        initializer
    {
        _setDomainSeperator(name);
    }

    function _setDomainSeperator(string memory name) internal {
        domainSeperator = keccak256(
            abi.encode(
                EIP712_DOMAIN_TYPEHASH,
                keccak256(bytes(name)),
                keccak256(bytes(ERC712_VERSION)),
                address(this),
                bytes32(getChainId())
            )
        );
    }

    function getDomainSeperator() public view returns (bytes32) {
        return domainSeperator;
    }

    function getChainId() public view returns (uint256) {
        uint256 id;
        assembly {
            id := chainid()
        }
        return id;
    }

    /**
     * Accept message hash and returns hash message in EIP712 compatible form
     * So that it can be used to recover signer from signature signed using EIP712 formatted data
     * https://eips.ethereum.org/EIPS/eip-712
     * "\\x19" makes the encoding deterministic
     * "\\x01" is the version byte to make it compatible to EIP-191
     */
    function toTypedMessageHash(bytes32 messageHash)
        internal
        view
        returns (bytes32)
    {
        return
            keccak256(
                abi.encodePacked("\x19\x01", getDomainSeperator(), messageHash)
            );
    }
}

// File: contracts/common/ContextMixin.sol



pragma solidity ^0.8.0;

abstract contract ContextMixin {
    function msgSender()
        internal
        view
        returns (address payable sender)
    {
        if (msg.sender == address(this)) {
            bytes memory array = msg.data;
            uint256 index = msg.data.length;
            assembly {
                // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
                sender := and(
                    mload(add(array, index)),
                    0xffffffffffffffffffffffffffffffffffffffff
                )
            }
        } else {
            sender = payable(msg.sender);
        }
        return sender;
    }
}
// File: @openzeppelin/contracts/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 no longer needed starting with Solidity 0.8. 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: contracts/common/NativeMetaTransaction.sol



pragma solidity ^0.8.0;



contract NativeMetaTransaction is EIP712Base {
    using SafeMath for uint256;
    bytes32 private constant META_TRANSACTION_TYPEHASH = keccak256(
        bytes(
            "MetaTransaction(uint256 nonce,address from,bytes functionSignature)"
        )
    );
    event MetaTransactionExecuted(
        address userAddress,
        address payable relayerAddress,
        bytes functionSignature
    );
    mapping(address => uint256) nonces;

    /*
     * Meta transaction structure.
     * No point of including value field here as if user is doing value transfer then he has the funds to pay for gas
     * He should call the desired function directly in that case.
     */
    struct MetaTransaction {
        uint256 nonce;
        address from;
        bytes functionSignature;
    }

    function executeMetaTransaction(
        address userAddress,
        bytes memory functionSignature,
        bytes32 sigR,
        bytes32 sigS,
        uint8 sigV
    ) public payable returns (bytes memory) {
        MetaTransaction memory metaTx = MetaTransaction({
            nonce: nonces[userAddress],
            from: userAddress,
            functionSignature: functionSignature
        });

        require(
            verify(userAddress, metaTx, sigR, sigS, sigV),
            "Signer and signature do not match"
        );

        // increase nonce for user (to avoid re-use)
        nonces[userAddress] = nonces[userAddress].add(1);

        emit MetaTransactionExecuted(
            userAddress,
            payable(msg.sender),
            functionSignature
        );

        // Append userAddress and relayer address at the end to extract it from calling context
        (bool success, bytes memory returnData) = address(this).call(
            abi.encodePacked(functionSignature, userAddress)
        );
        require(success, "Function call not successful");

        return returnData;
    }

    function hashMetaTransaction(MetaTransaction memory metaTx)
        internal
        pure
        returns (bytes32)
    {
        return
            keccak256(
                abi.encode(
                    META_TRANSACTION_TYPEHASH,
                    metaTx.nonce,
                    metaTx.from,
                    keccak256(metaTx.functionSignature)
                )
            );
    }

    function getNonce(address user) public view returns (uint256 nonce) {
        nonce = nonces[user];
    }

    function verify(
        address signer,
        MetaTransaction memory metaTx,
        bytes32 sigR,
        bytes32 sigS,
        uint8 sigV
    ) internal view returns (bool) {
        require(signer != address(0), "NativeMetaTransaction: INVALID_SIGNER");
        return
            signer ==
            ecrecover(
                toTypedMessageHash(hashMetaTransaction(metaTx)),
                sigV,
                sigR,
                sigS
            );
    }
}

// File: @openzeppelin/contracts/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);
    }
}

// File: @openzeppelin/contracts/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: @openzeppelin/contracts/access/Ownable.sol



pragma solidity ^0.8.0;


/**
 * @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() {
        _setOwner(_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 {
        _setOwner(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");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// File: @openzeppelin/contracts/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: @openzeppelin/contracts/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: @openzeppelin/contracts/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: @openzeppelin/contracts/utils/introspection/ERC165.sol



pragma solidity ^0.8.0;


/**
 * @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: @openzeppelin/contracts/token/ERC721/IERC721.sol



pragma solidity ^0.8.0;


/**
 * @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: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol



pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol



pragma solidity ^0.8.0;


/**
 * @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: @openzeppelin/contracts/token/ERC721/ERC721.sol



pragma solidity ^0.8.0;








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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        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 {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

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

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: 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 _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, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

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

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

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

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

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

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

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

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

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

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

    /**
     * @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);

        _balances[from] -= 1;
        _balances[to] += 1;
        _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 Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    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: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol



pragma solidity ^0.8.0;



/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

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

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

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

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

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return _ownedTokens[owner][index];
    }

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

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
        return _allTokens[index];
    }

    /**
     * @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` cannot be the zero address.
     * - `to` cannot be the zero address.
     *
     * 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 override {
        super._beforeTokenTransfer(from, to, tokenId);

        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = ERC721.balanceOf(to);
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

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

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

// File: contracts/ERC721Tradable.sol



pragma solidity ^0.8.0;








contract OwnableDelegateProxy {}

contract ProxyRegistry {
    mapping(address => OwnableDelegateProxy) public proxies;
}

/**
 * @title ERC721Tradable
 * ERC721Tradable - ERC721 contract that whitelists a trading address, and has minting functionality.
 */
abstract contract ERC721Tradable is ContextMixin, ERC721Enumerable, NativeMetaTransaction, Ownable {
    using SafeMath for uint256;

    address proxyRegistryAddress;
    uint256 private _currentTokenId = 0;

    constructor(
        string memory _name,
        string memory _symbol,
        address _proxyRegistryAddress
    ) ERC721(_name, _symbol) {
        proxyRegistryAddress = _proxyRegistryAddress;
        _initializeEIP712(_name);
    }

    /**
     * Override isApprovedForAll to whitelist user's OpenSea proxy accounts to enable gas-less listings.
     */
    function isApprovedForAll(address owner, address operator)
        override
        public
        view
        returns (bool)
    {
        // Whitelist OpenSea proxy contract for easy trading.
        ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
        if (address(proxyRegistry.proxies(owner)) == operator) {
            return true;
        }

        return super.isApprovedForAll(owner, operator);
    }

    /**
     * This is used instead of msg.sender as transactions won't be sent by the original token owner, but by OpenSea.
     */
    function _msgSender()
        internal
        override
        view
        returns (address sender)
    {
        return ContextMixin.msgSender();
    }
}

// File: contracts/BitKoi.sol



pragma solidity ^0.8.0;

/**
 * @title BitKoi
 * BitKoi - a blockchain game at scale
 */

/// @title mix up two fish and find out which traits they should have
abstract contract BitKoiTraitInterface {
    /// @dev simply a boolean to indicate this is the contract we expect to be
    function isBitKoiTraits() virtual public pure returns (bool);

    ///mix up the "genes" of the fish to see which genes our new fish will have
    function smooshFish(uint256 genes1, uint256 genes2, uint256 targetBlock) virtual public returns (uint256);
}

/// @title A facet of BitKoiCore that manages special access privileges.
/// Based on work from Axiom Zen (https://www.axiomzen.co)
contract BitKoiAccessControl {

    // The addresses of the accounts (or contracts) that can execute actions within each roles.
    address public ceoAddress;
    address public cfoAddress;
    address public cooAddress;

    // @dev Keeps track whether the contract is paused.
    bool public paused = false;

    modifier onlyCEO() {
        require(msg.sender == ceoAddress);
        _;
    }

    modifier onlyCFO() {
        require(msg.sender == cfoAddress);
        _;
    }

    modifier onlyCOO() {
        require(msg.sender == cooAddress);
        _;
    }

    modifier onlyCLevel() {
        require(
            msg.sender == cooAddress ||
            msg.sender == ceoAddress ||
            msg.sender == cfoAddress
        );
        _;
    }

    /// @dev Assigns a new address to act as the CEO. Only available to the current CEO.
    /// @param _newCEO The address of the new CEO
    function setCEO(address _newCEO) external onlyCEO {
        require(_newCEO != address(0));

        ceoAddress = _newCEO;
    }

    /// @dev Assigns a new address to act as the CFO. Only available to the current CEO.
    /// @param _newCFO The address of the new CFO
    function setCFO(address payable _newCFO) external onlyCEO {
        require(_newCFO != address(0));

        cfoAddress = _newCFO;
    }

    /// @dev Assigns a new address to act as the COO. Only available to the current CEO.
    /// @param _newCOO The address of the new COO
    function setCOO(address _newCOO) external onlyCEO {
        require(_newCOO != address(0));

        cooAddress = _newCOO;
    }

    /*** Pausable functionality adapted from OpenZeppelin ***/

    /// @dev Modifier to allow actions only when the contract IS NOT paused
    modifier whenNotPaused() {
        require(!paused);
        _;
    }

    /// @dev Modifier to allow actions only when the contract IS paused
    modifier whenPaused {
        require(paused);
        _;
    }

    /// @dev Called by any "C-level" role to pause the contract. Used only when
    ///  a bug or exploit is detected and we need to limit damage.
    function pause() external onlyCLevel whenNotPaused {
        paused = true;
    }

    /// @dev Unpauses the smart contract. Can only be called by the CEO, since
    ///  one reason we may pause the contract is when CFO or COO accounts are
    ///  compromised.
    /// @notice This is public rather than external so it can be called by
    ///  derived contracts.
    function unpause() virtual public onlyCEO whenPaused {
        // can't unpause if contract was upgraded
        paused = false;
    }
}


/// @title Base contract for KoiPond. Holds all common structs, events and base variables.
/// based on code written for CK by Axiom Zen (https://www.axiomzen.co)
abstract contract BitKoiBase is BitKoiAccessControl, ERC721Tradable {
    /*** EVENTS ***/

    /// @dev The Spawn event is fired whenever a new fish comes into existence. This obviously
    ///  includes any time a fish is created through the spawnFish method, but it is also called
    ///  when a new gen0 fish is created.
    event Spawn(address owner, uint256 koiFishId, uint256 parent1Id, uint256 parent2Id, uint256 genes, uint16 generation, uint64 timestamp);

    event BreedingSuccessful(address owner, uint256 newFishId, uint256 parent1Id, uint256 parent2Id, uint64 cooldownEndBlock);

    /*** DATA TYPES ***/

    struct BitKoi {
        // The fish's genetic code - this will never change for any fish.
        uint256 genes;

        // The timestamp from the block when this fish came into existence.
        uint64 spawnTime;

        // The minimum timestamp after which this fish can engage in spawning
        // activities again.
        uint64 cooldownEndBlock;

        // The ID of the parents of this fish, set to 0 for gen0 fish.
        // With uint32 there's a limit of 4 billion fish
        uint32 parent1Id;
        uint32 parent2Id;

        // Set to the index in the cooldown array (see below) that represents
        // the current cooldown duration for this fish. This starts at zero
        // for gen0 fish, and is initialized to floor(generation/2) for others.
        // Incremented by one for each successful breeding action.
        uint16 cooldownIndex;

        // The "generation number" of this fish. Fish minted by the KP contract
        // for sale are called "gen0" and have a generation number of 0. The
        // generation number of all other fish is the larger of the two generation
        // numbers of their parents, plus one.
        uint16 generation;
    }

    /*** CONSTANTS ***/

    /// @dev A lookup table indicating the cooldown duration after any successful
    ///  breeding action, called "cooldown" Designed such that the cooldown roughly
    ///  doubles each time a fish is bred, encouraging owners not to just keep breeding the same fish over
    ///  and over again. Caps out at one week (a fish can breed an unbounded number
    ///  of times, and the maximum cooldown is always seven days).
    uint32[14] public cooldowns = [
        uint32(1 minutes),
        uint32(2 minutes),
        uint32(5 minutes),
        uint32(10 minutes),
        uint32(30 minutes),
        uint32(1 hours),
        uint32(2 hours),
        uint32(4 hours),
        uint32(8 hours),
        uint32(16 hours),
        uint32(1 days),
        uint32(2 days),
        uint32(4 days),
        uint32(7 days)
    ];

    // An approximation of currently how many seconds are in between blocks.
    uint256 public secondsPerBlock = 15;

    /*** STORAGE ***/

    /// @dev An array containing the KoiFish struct for all KoiFish in existence. The ID
    /// of each fish is actually an index into this array. Fish 0 has an invalid genetic
    /// code and can't be used to produce offspring.
    BitKoi[] bitKoi;

    /// @dev A mapping from fish IDs to the address that owns them. All fish have
    ///  some valid owner address, even gen0 fish are created with a non-zero owner.
    mapping (uint256 => address) bitKoiIndexToOwner;

    // @dev A mapping from owner address to count of tokens that address owns.
    //  Used internally inside balanceOf() to resolve ownership count.
    mapping (address => uint256) ownershipTokenCount;

    /// @dev A mapping from KoiFishIDs to an address that has been approved to call
    ///  transferFrom(). Each KoiFish can only have one approved address for transfer
    ///  at any time. A zero value means no approval is outstanding.
    mapping (uint256 => address) bitKoiIndexToApproved;

    // /// @dev Assigns ownership of a specific KoiFish to an address.
    function _transfer(address _from, address _to, uint256 _tokenId) override internal {
        require(ownerOf(_tokenId) == _from, "ERC721: transfer of token that is not own");
        require(_to != address(0), "ERC721: transfer to the zero address");
        // Since the number of fish is capped to 2^32 we can't overflow this
        ownershipTokenCount[_to]++;
        ownershipTokenCount[_from]--;

        _beforeTokenTransfer(_from, _to, _tokenId);

        // actually transfer ownership
        bitKoiIndexToOwner[_tokenId] = _to;

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

        emit Transfer(_from, _to, _tokenId);

    }

    /// @notice Returns the address currently assigned ownership of a given BitKoi.
    /// @dev Required for ERC-721 compliance.
    function ownerOf(uint256 _tokenId)
        override
        public
        view
        returns (address owner)
    {
        owner = bitKoiIndexToOwner[_tokenId];
        require(owner != address(0));
    }

     function balanceOf(address owner) public view override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return ownershipTokenCount[owner];
    }

    /// @notice Returns a list of all KoiFish IDs assigned to an address.
    /// @param _owner The owner whose KoiFish we are interested in.
    /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly
    ///  expensive (it walks the entire KoiFish array looking for fish belonging to owner),
    ///  but it also returns a dynamic array, which is only supported for web3 calls, and
    ///  not contract-to-contract calls.
    function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) {
        uint256 tokenCount = balanceOf(_owner);

        if (tokenCount == 0) {
            // Return an empty array
            return new uint256[](0);
        } else {
            uint256[] memory result = new uint256[](tokenCount);
            uint256 totalBitKoi = totalSupply();
            uint256 resultIndex = 0;

            // We count on the fact that all fish have IDs starting at 1 and increasing
            // sequentially up to the totalKoi count.
            uint256 bitKoiId;

            for (bitKoiId = 1; bitKoiId <= totalBitKoi; bitKoiId++) {
                if (bitKoiIndexToOwner[bitKoiId] == _owner) {
                    result[resultIndex] = bitKoiId;
                    resultIndex++;
                }
            }
            return result;
        }
    }

    function _mintNewKoi(address _to, uint256 _tokenId) internal {
        _mint(_to, _tokenId);

        // Since the number of fish is capped to 2^32 we can't overflow this
        ownershipTokenCount[_to]++;

        // transfer ownership
        bitKoiIndexToOwner[_tokenId] = _to;
    }

    // Any C-level can fix how many seconds per blocks are currently observed.
    function setSecondsPerBlock(uint256 secs) external onlyCLevel {
        require(secs < cooldowns[0]);
        secondsPerBlock = secs;
    }
}

abstract contract BitKoiOwnership is BitKoiBase {
    /// @dev Returns true if the claimant owns the token.
    /// @param _claimant - Address claiming to own the token.
    /// @param _tokenId - ID of token whose ownership to verify.
    function _owns(
        address _claimant,
        uint256 _tokenId
    )
        internal
        view
        returns (bool) {

        return (ownerOf(_tokenId) == _claimant);
    }

    /// @dev Checks if a given address currently has transferApproval for a particular KoiFish.
    /// @param _claimant the address we are confirming fish is approved for.
    /// @param _tokenId fish id, only valid when > 0
    function _approvedFor(
        address _claimant,
        uint256 _tokenId
    )
        internal
        view
        returns (bool) {

        return bitKoiIndexToApproved[_tokenId] == _claimant;
    }

    /// @dev Marks an address as being approved for transferFrom(), overwriting any previous
    ///  approval. Setting _approved to address(0) clears all transfer approval.
    ///  NOTE: _approve() does NOT send the Approval event. This is intentional because
    ///  _approve() and transferFrom() are used together for putting KoiFish on auction, and
    ///  there is no value in spamming the log with Approval events in that case.
    function _approve(
        uint256 _tokenId,
        address _approved
    )
        internal {

        bitKoiIndexToApproved[_tokenId] = _approved;
    }

    function transfer(
        address _to,
        uint256 _tokenId
    )
        external
        whenNotPaused
    {
        // Safety check to prevent against an unexpected 0x0 default.
        require(_to != address(0));
        // Disallow transfers to this contract to prevent accidental misuse.
        // The contract should never own any fish (except very briefly
        // after a gen0 fish is created and before it goes on auction).
        require(_to != address(this));
        // Disallow transfers to the auction contracts to prevent accidental
        // misuse. Auction contracts should only take ownership of fish
        // through the allow + transferFrom flow.

        // You can only send your own fish
        require(_owns(msg.sender, _tokenId));

        // Reassign ownership, clear pending approvals, emit Transfer event.
        _transfer(msg.sender, _to, _tokenId);
    }

}

abstract contract BitKoiBreeding is BitKoiOwnership {
    event Hatch(address owner, uint256 fishId, uint256 genes);

    uint256 public breedFee = 0 wei;

    uint256 public hatchFee = 0 wei;

    /// @dev The address of the sibling contract that is used to implement the genetic combination algorithm.
    BitKoiTraitInterface public bitKoiTraits;

    /// @dev Update the address of the genetic contract, can only be called by the CEO.
    /// @param _address An address of a GeneScience contract instance to be used from this point forward.
    function setBitKoiTraitAddress(address _address) external onlyCEO {
        BitKoiTraitInterface candidateContract = BitKoiTraitInterface(_address);

        // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117
        require(candidateContract.isBitKoiTraits());

        // Set the new contract address
        bitKoiTraits = candidateContract;
    }

    /// @dev Checks to see if a given fish is ready to hatch after the gestation period has passed.
    function _isReadyToHatch(uint256 _fishId) private view returns (bool) {
        BitKoi storage fishToHatch = bitKoi[_fishId];
        return fishToHatch.cooldownEndBlock <= uint64(block.number);
    }

    /// @dev Checks that a given fish is able to breed. Requires that the
    ///  current cooldown is finished

    function _isReadyToBreed(BitKoi storage _fish) internal view returns (bool) {
        // In addition to checking the cooldownEndBlock, we also need to check to see if
        // the fish has a pending birth; there can be some period of time between the end
        // of the pregnacy timer and the spawn event.
        return _fish.cooldownEndBlock <= uint64(block.number);
    }

    /// @dev Set the cooldownEndTime for the given fish based on its current cooldownIndex.
    ///  Also increments the cooldownIndex (unless it has hit the cap).
    /// @param _koiFish A reference to the KoiFish in storage which needs its timer started.
    function _triggerCooldown(BitKoi storage _koiFish) internal {
        // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex).
        _koiFish.cooldownEndBlock = uint64((cooldowns[_koiFish.cooldownIndex]/secondsPerBlock) + block.number);

        // Increment the breeding count, clamping it at 13, which is the length of the
        // cooldowns array. We could check the array size dynamically, but hard-coding
        // this as a constant saves gas. Yay, Solidity!
        if (_koiFish.cooldownIndex < 13) {
            _koiFish.cooldownIndex += 1;
        }
    }

    // @dev Updates the minimum payment required for calling breedWith(). Can only
    ///  be called by the COO address. (This fee is used to offset the gas cost incurred
    ///  by the autobirth daemon).
    function setBreedFee(uint256 val) external onlyCEO {
        breedFee = val;
    }

    // @dev Updates the minimum payment required for calling hatchFish(). Can only
    ///  be called by the COO address. (This fee is used to offset the gas cost incurred
    ///  by the autobirth daemon).
    function setHatchFee(uint256 val) external onlyCEO {
        hatchFee = val;
    }

    /// @notice Checks that a given fish is able to breed (i.e. it is not
    ///  in the middle of a siring cooldown).
    /// @param _koiId reference the id of the fish, any user can inquire about it
    function isReadyToBreed(uint256 _koiId)
        public
        view
        returns (bool)
    {
        require(_koiId > 0);
        BitKoi storage fish = bitKoi[_koiId];
        return _isReadyToBreed(fish);
    }

    /// @notice Checks that a given fish is able to breed (i.e. it is not
    ///  in the middle of a siring cooldown).
    /// @param _koiId reference the id of the fish, any user can inquire about it
    function isReadyToHatch(uint256 _koiId)
        public
        view
        returns (bool)
    {
        require(_koiId > 0);
        return _isReadyToHatch(_koiId);
    }

    /// @dev Internal check to see if a the parents are a valid mating pair. DOES NOT
    ///  check ownership permissions (that is up to the caller).
    /// @param _parent1 A reference to the Fish struct of the potential first parent
    /// @param _parent1Id The first parent's ID.
    /// @param _parent2 A reference to the Fish struct of the potential second parent
    /// @param _parent2Id The second parent's ID.
    function _isValidMatingPair(
        BitKoi storage _parent1,
        uint256 _parent1Id,
        BitKoi storage _parent2,
        uint256 _parent2Id
    )
        private
        view
        returns(bool)
    {
        // A Fish can't breed with itself!
        if (_parent1Id == _parent2Id) {
            return false;
        }

        //the fish have to have genes
        if (_parent1.genes == 0 || _parent2.genes == 0) {
            return false;
        }

        // Fish can't breed with their parents.
        if (_parent1.parent1Id == _parent1Id || _parent1.parent2Id == _parent2Id) {
            return false;
        }
        if (_parent2.parent1Id == _parent1Id || _parent2.parent2Id == _parent2Id) {
            return false;
        }

        // OK the tx if either fish is gen zero (no parent found).
        if (_parent2.parent1Id == 0 || _parent1.parent1Id == 0) {
            return true;
        }

        // Fish can't breed with full or half siblings.
        if (_parent2.parent1Id == _parent1.parent1Id || _parent2.parent1Id == _parent1.parent2Id) {
            return false;
        }
        if (_parent2.parent1Id == _parent1.parent1Id || _parent2.parent2Id == _parent1.parent2Id) {
            return false;
        }

        // gtg
        return true;
    }

    /// @notice Checks to see if two BitKoi can breed together, including checks for
    ///     ownership and siring approvals. Doesn't check that both BitKoi are ready for
    ///     breeding (i.e. breedWith could still fail until the cooldowns are finished).
    /// @param _parent1Id The ID of the proposed first parent.
    /// @param _parent2Id The ID of the proposed second parent.
    function canBreedWith(uint256 _parent1Id, uint256 _parent2Id)
        external
        view
        returns(bool)
    {
        require(_parent1Id > 0);
        require(_parent2Id > 0);
        BitKoi storage parent1 = bitKoi[_parent1Id];
        BitKoi storage parent2 = bitKoi[_parent2Id];
        return _isValidMatingPair(parent1, _parent1Id, parent2, _parent2Id);
    }

    /// @dev Internal utility function to initiate breeding, assumes that all breeding
    ///     requirements have been checked.
    function _breedWith(uint256 _parent1Id, uint256 _parent2Id) internal returns(uint256) {
        // Grab a reference to the Koi from storage.
        BitKoi storage parent1 = bitKoi[_parent1Id];
        BitKoi storage parent2 = bitKoi[_parent2Id];

        // Determine the higher generation number of the two parents
        uint16 parentGen = parent1.generation;
        if (parent2.generation > parent1.generation) {
            parentGen = parent2.generation;
        }

        uint256 bitKoiCoProceeds = msg.value;

        //transfer the breed fee less the pond cut to the CFO contract
        payable(address(cfoAddress)).transfer(bitKoiCoProceeds);

        // Make the new fish!
        address owner = bitKoiIndexToOwner[_parent1Id];
        uint256 newFishId = _createBitKoi(_parent1Id, _parent2Id, parentGen + 1, 0, owner);

        // Trigger the cooldown for both parents.
        _triggerCooldown(parent1);
        _triggerCooldown(parent2);

        // Emit the breeding event.
        emit BreedingSuccessful(bitKoiIndexToOwner[_parent1Id], newFishId, _parent1Id, _parent2Id, parent1.cooldownEndBlock);

        return newFishId;
    }

    function breedWith(uint256 _parent1Id, uint256 _parent2Id)
        external
        payable
        whenNotPaused
    {
        // Checks for payment.
        require(msg.value >= breedFee);

        ///check to see if the caller owns both fish
        require(_owns(msg.sender, _parent1Id));
        require(_owns(msg.sender, _parent2Id));

        // Grab a reference to the first parent
        BitKoi storage parent1 = bitKoi[_parent1Id];

        // Make sure enough time has passed since the last time this fish was bred
        require(_isReadyToBreed(parent1));

        // Grab a reference to the second parent
        BitKoi storage parent2 = bitKoi[_parent2Id];

        // Make sure enough time has passed since the last time this fish was bred
        require(_isReadyToBreed(parent2));

        // Test that these fish are a valid mating pair.
        require(_isValidMatingPair(
            parent2,
            _parent2Id,
            parent1,
            _parent1Id
        ));

        // All checks passed, make a new fish!!
        _breedWith(_parent1Id, _parent2Id);
    }

    /// @dev An internal method that creates a new fish and stores it. This
    ///  method doesn't do any checking and should only be called when the
    ///  input data is known to be valid. Will generate both a Birth event
    ///  and a Transfer event.
    /// @param _parent1Id The fish ID of the first parent (zero for gen0)
    /// @param _parent2Id The fish ID of the second parent (zero for gen0)
    /// @param _generation The generation number of this fish, must be computed by caller.
    /// @param _genes The fish's genetic code.
    /// @param _owner The inital owner of this fish, must be non-zero (except for fish ID 0)
    function _createBitKoi(
        uint256 _parent1Id,
        uint256 _parent2Id,
        uint256 _generation,
        uint256 _genes,
        address _owner
    )
        internal
        returns (uint)
    {
        // These requires are not strictly necessary, our calling code should make
        // sure that these conditions are never broken. However! _createKoiFish() is already
        // an expensive call (for storage), and it doesn't hurt to be especially careful
        // to ensure our data structures are always valid.
        require(_parent1Id == uint256(uint32(_parent1Id)));
        require(_parent2Id == uint256(uint32(_parent2Id)));
        require(_generation == uint256(uint16(_generation)));

        // New fish starts with the same cooldown as parent gen/2
        uint16 cooldownIndex = uint16(_generation / 2);
        if (cooldownIndex > 13) {
            cooldownIndex = 13;
        }

        BitKoi memory _bitKoi = BitKoi({
            genes: _genes,
            spawnTime: uint64(block.timestamp),
            cooldownEndBlock: 0,
            parent1Id: uint32(_parent1Id),
            parent2Id: uint32(_parent2Id),
            cooldownIndex: cooldownIndex,
            generation: uint16(_generation)
        });

        uint256 newBitKoiId = bitKoi.length;
        bitKoi.push(_bitKoi);

        // It's probably never going to happen, 4 billion fish is A LOT, but
        // let's just be 100% sure we never let this happen.
        require(newBitKoiId == uint256(uint32(newBitKoiId)));

        // This will assign ownership, and also emit the Transfer event as
        // per ERC721 draft
        _mintNewKoi(_owner, newBitKoiId);

        // emit the spawn event
        emit Spawn(
            _owner,
            newBitKoiId,
            uint256(_bitKoi.parent1Id),
            uint256(_bitKoi.parent2Id),
            _bitKoi.genes,
            uint16(_generation),
            uint64(block.timestamp)
        );

        BitKoi storage brandNewKoi = bitKoi[newBitKoiId];

        _triggerCooldown(brandNewKoi);

        return newBitKoiId;
    }


    function hatchFish(uint256 _fishId, uint256 _geneSet1, uint256 _geneSet2)
        external
        payable
        whenNotPaused
    {
        // Checks for payment.
        require(msg.value >= hatchFee);

        //ensure the caller owns the egg they want to hatch
        require(_owns(msg.sender, _fishId));

        _hatchFish(_fishId, _geneSet1, _geneSet2);
    }

    function _hatchFish(uint256 _fishId, uint256 _geneSet1, uint256 _geneSet2) internal {
        BitKoi storage fishToHatch = bitKoi[_fishId];

        BitKoi storage parent1 = bitKoi[fishToHatch.parent1Id];
        BitKoi storage parent2 = bitKoi[fishToHatch.parent2Id];

        uint256 genes1 = 0;
        uint256 genes2 = 0;

        if (fishToHatch.parent1Id > 0){
            genes1 = parent1.genes;
        } else {
            genes1 = _geneSet1;
        }

        if (fishToHatch.parent2Id > 0){
            genes2 = parent2.genes;
        } else {
            genes2 = _geneSet2;
        }

        // Check that the parent is a valid fish
        require(parent1.spawnTime != 0 && parent2.spawnTime != 0);

        // Check to see if the fish is ready to hatch
        require(_isReadyToHatch(_fishId));

        // Make sure this fish doesn't already have genes
        require(fishToHatch.genes == 0);

        // next, let's get new genes for the fish we're about to hatch
        uint256 newFishGenes = bitKoiTraits.smooshFish(genes1, genes2, fishToHatch.cooldownEndBlock - 1);

        fishToHatch.genes = uint256(newFishGenes);

        //transfer the hatch fee less the pond cut to the CFO contract
        payable(address(cfoAddress)).transfer(msg.value);

        emit Hatch(msg.sender, _fishId, newFishGenes);
    }

}

abstract contract BitKoiAuction is BitKoiBreeding {
        // Tracks last 5 sale price of gen0 fish sales
        uint256 public gen0SaleCount;
        uint256[5] public lastGen0SalePrices;

        struct Auction {
            // Current owner of NFT
            address seller;
            // Price (in wei) at beginning of auction
            uint128 startingPrice;
            // Price (in wei) at end of auction
            uint128 endingPrice;
            // Duration (in seconds) of auction
            uint64 duration;
            // Time when auction started
            // NOTE: 0 if this auction has been concluded
            uint64 startedAt;
        }

        // Cut contract owner takes on each auction, measured in basis points (1/100 of a percent).
        // Values 0-10,000 map to 0%-100%
        uint256 public ownerCut = 250;

        /// @param _ownerCut - update the percent cut the contract owner takes on each breed or hatch event, must be
        ///  between 0-10,000.
        function setOwnerCut(uint256 _ownerCut) external onlyCEO {
            require(_ownerCut <= 10000);
            ownerCut = _ownerCut;
        }

        // Map from token ID to their corresponding auction.
        mapping (uint256 => Auction) tokenIdToAuction;

        event AuctionCreated(address sellerId, uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration, uint256 startedAt);
        event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner);
        event AuctionCancelled(uint256 tokenId);

        /// @dev adds an auction to the list of open auctions. Also fires the AuctionCreated event.
        /// @param _tokenId The ID of the token to be put on auction.
        /// @param _auction Auction to add.
        function _addAuction(address _sellerId, uint256 _tokenId, Auction memory _auction, uint256 _auctionStarted) internal {
            // Require that all auctions have a duration of
            // at least one minute. (Keeps our math from getting hairy!)
            require(_auction.duration >= 0 minutes);

            tokenIdToAuction[_tokenId] = _auction;

            emit AuctionCreated(
                address(_sellerId),
                uint256(_tokenId),
                uint256(_auction.startingPrice),
                uint256(_auction.endingPrice),
                uint256(_auction.duration),
                uint256(_auctionStarted)
            );
        }

        /// @dev Cancels an auction unconditionally.
        function _cancelAuction(uint256 _tokenId) internal {
            _removeAuction(_tokenId);
            emit AuctionCancelled(_tokenId);
        }

        /// @dev Computes the price and transfers winnings.
        /// Does NOT transfer ownership of token.
        function _bid(uint256 _tokenId, uint256 _bidAmount)
            internal
            returns (uint256)
        {
            // Get a reference to the auction struct
            Auction storage auction = tokenIdToAuction[_tokenId];

            // Explicitly check that this auction is currently live.
            // (Because of how Ethereum mappings work, we can't just count
            // on the lookup above failing. An invalid _tokenId will just
            // return an auction object that is all zeros.)
            require(_isOnAuction(auction));

            // Check that the bid is greater than or equal to the current price
            uint256 price = _currentPrice(auction);
            require(_bidAmount >= price);

            address seller = address(uint160(auction.seller));


            // The bid is good! Remove the auction before sending the fees
            // to the sender so we can't have a reentrancy attack.
            _removeAuction(_tokenId);

            // Transfer proceeds to seller (if there are any!)
            if (price > 0) {
                // Calculate the auctioneer's cut.
                // (NOTE: _computeCut() is guaranteed to return a
                // value <= price, so this subtraction can't go negative.)
                uint256 contractCut = _computeCut(price);
                uint256 sellerProceeds = price - contractCut;

                // NOTE: Doing a transfer() in the middle of a complex
                // method like this is generally discouraged because of
                // reentrancy attacks and DoS attacks if the seller is
                // a contract with an invalid fallback function. We explicitly
                // guard against reentrancy attacks by removing the auction
                // before calling transfer(), and the only thing the seller
                // can DoS is the sale of their own asset! (And if it's an
                // accident, they can call cancelAuction(). )

                payable(cfoAddress).transfer(contractCut);

                payable(seller).transfer(sellerProceeds);
            }


            // Calculate any excess funds included with the bid. If the excess
            // is anything worth worrying about, transfer it back to bidder.
            // NOTE: We checked above that the bid amount is greater than or
            // equal to the price so this cannot underflow.
            uint256 bidExcess = _bidAmount - price;

            // Return the funds. Similar to the previous transfer, this is
            // not susceptible to a re-entry attack because the auction is
            // removed before any transfers occur.

            payable(msg.sender).transfer(bidExcess);

            // Tell the world!
            emit AuctionSuccessful(_tokenId, price, msg.sender);

            return price;
        }

        /// @dev Removes an auction from the list of open auctions.
        /// @param _tokenId - ID of NFT on auction.
        function _removeAuction(uint256 _tokenId) internal {
            delete tokenIdToAuction[_tokenId];
        }

        /// @dev Returns true if the NFT is on auction.
        /// @param _auction - Auction to check.
        function _isOnAuction(Auction storage _auction) internal view returns (bool) {
            return (_auction.startedAt > 0);
        }

        /// @dev Returns current price of an NFT on auction. Broken into two
        ///  functions (this one, that computes the duration from the auction
        ///  structure, and the other that does the price computation) so we
        ///  can easily test that the price computation works correctly.
        function _currentPrice(Auction storage _auction)
            internal
            view
            returns (uint256)
        {
            uint256 secondsPassed = 0;

            // A bit of insurance against negative values (or wraparound).
            // Probably not necessary (since Ethereum guarnatees that the
            // now variable doesn't ever go backwards).
            if (block.timestamp > _auction.startedAt) {
                secondsPassed = block.timestamp - _auction.startedAt;
            }

            return _computeCurrentPrice(
                _auction.startingPrice,
                _auction.endingPrice,
                _auction.duration,
                secondsPassed
            );
        }

        /// @dev Computes the current price of an auction. Factored out
        ///  from _currentPrice so we can run extensive unit tests.
        ///  When testing, make this function public and turn on
        ///  `Current price computation` test suite.
        function _computeCurrentPrice(
            uint256 _startingPrice,
            uint256 _endingPrice,
            uint256 _duration,
            uint256 _secondsPassed
        )
            internal
            pure
            returns (uint256)
        {
            // NOTE: We don't use SafeMath (or similar) in this function because
            //  all of our public functions carefully cap the maximum values for
            //  time (at 64-bits) and currency (at 128-bits). _duration is
            //  also known to be non-zero (see the require() statement in
            //  _addAuction())
            if (_secondsPassed >= _duration) {
                // We've reached the end of the dynamic pricing portion
                // of the auction, just return the end price.
                return _endingPrice;
            } else {
                // Starting price can be higher than ending price (and often is!), so
                // this delta can be negative.
                int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice);

                // This multiplication can't overflow, _secondsPassed will easily fit within
                // 64-bits, and totalPriceChange will easily fit within 128-bits, their product
                // will always fit within 256-bits.
                int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration);

                // currentPriceChange can be negative, but if so, will have a magnitude
                // less that _startingPrice. Thus, this result will always end up positive.
                int256 currentPrice = int256(_startingPrice) + currentPriceChange;

                return uint256(currentPrice);
            }
        }

        /// @dev Computes owner's cut of a sale.
        /// @param _price - Sale price of NFT.
        function _computeCut(uint256 _price) internal view returns (uint256) {
            // NOTE: We don't use SafeMath (or similar) in this function because
            //  all of our entry functions carefully cap the maximum values for
            //  currency (at 128-bits), and ownerCut <= 10000 (see the require()
            //  statement in the ClockAuction constructor). The result of this
            //  function is always guaranteed to be <= _price.
            return _price * ownerCut / 10000;
        }

        /// @dev Creates and begins a new auction.
        /// @param _tokenId - ID of token to auction, sender must be owner.
        /// @param _startingPrice - Price of item (in wei) at beginning of auction.
        /// @param _endingPrice - Price of item (in wei) at end of auction.
        /// @param _duration - Length of auction (in seconds).
        /// @param _seller - Seller, if not the message sender
        function createAuction(
            uint256 _tokenId,
            uint256 _startingPrice,
            uint256 _endingPrice,
            uint256 _duration,
            address _seller
        )
            external
            whenNotPaused
        {
            // Sanity check that no inputs overflow how many bits we've allocated
            // to store them in the auction struct.
            require(_startingPrice == uint256(uint128(_startingPrice)));
            require(_endingPrice == uint256(uint128(_endingPrice)));
            require(_duration == uint256(uint64(_duration)));
            require(_startingPrice >= _endingPrice);
            require(msg.sender == bitKoiIndexToOwner[_tokenId]);

            Auction memory auction = Auction(
                address(_seller),
                uint128(_startingPrice),
                uint128(_endingPrice),
                uint64(_duration),
                uint64(block.timestamp)
            );
            _addAuction(_seller, _tokenId, auction, block.timestamp);
        }

        function bid(uint256 _tokenId)
            external
            payable
            whenNotPaused
        {
            // _bid will throw if the bid or funds transfer fails
            // _bid verifies token ID size
            address seller = tokenIdToAuction[_tokenId].seller;
            uint256 price = _bid(_tokenId, msg.value);

            //If not a gen0 auction, exit
            if (seller == address(this)) {
                // Track gen0 sale prices
                lastGen0SalePrices[gen0SaleCount % 5] = price;
                gen0SaleCount++;
            }

            _transfer(seller, msg.sender, _tokenId);
        }

        function averageGen0SalePrice() external view returns (uint256) {
            uint256 sum = 0;
            for (uint256 i = 0; i < 5; i++) {
                sum += lastGen0SalePrices[i];
            }
            return sum / 5;
        }

        /// @dev Cancels an auction that hasn't been won yet.
    ///  Returns the NFT to original owner.
    /// @notice This is a state-modifying function that can
    ///  be called while the contract is paused.
    /// @param _tokenId - ID of token on auction
    function cancelAuction(uint256 _tokenId)
        external
    {
        Auction storage auction = tokenIdToAuction[_tokenId];
        require(_isOnAuction(auction));
        address seller = auction.seller;
        require(msg.sender == seller);
        _cancelAuction(_tokenId);
    }

    /// @dev Cancels an auction when the contract is paused.
    ///  Only the owner may do this, and NFTs are returned to
    ///  the seller. This should only be used in emergencies.
    /// @param _tokenId - ID of the NFT on auction to cancel.
    function cancelAuctionWhenPaused(uint256 _tokenId)
        whenPaused
        onlyOwner
        external
    {
        Auction storage auction = tokenIdToAuction[_tokenId];
        require(_isOnAuction(auction));
        _cancelAuction(_tokenId);
    }

    /// @dev Returns auction info for an NFT on auction.
    /// @param _tokenId - ID of NFT on auction.
    function getAuction(uint256 _tokenId)
        external
        view
        returns
    (
        address seller,
        uint256 startingPrice,
        uint256 endingPrice,
        uint256 duration,
        uint256 startedAt
    ) {
        Auction storage auction = tokenIdToAuction[_tokenId];
        require(_isOnAuction(auction));
        return (
            auction.seller,
            auction.startingPrice,
            auction.endingPrice,
            auction.duration,
            auction.startedAt
        );
    }

    /// @dev Returns the current price of an auction.
    /// @param _tokenId - ID of the token price we are checking.
    function getCurrentPrice(uint256 _tokenId)
        external
        view
        returns (uint256)
    {
        Auction storage auction = tokenIdToAuction[_tokenId];
        require(_isOnAuction(auction));
        return _currentPrice(auction);
    }
}

/// @title all functions related to creating fish (and their eggs)
abstract contract BitKoiMinting is BitKoiAuction {

    // Limits the number of fish the contract owner can ever create.
    uint256 public constant PROMO_CREATION_LIMIT = 5000;
    uint256 public constant GEN0_EGG_CREATION_LIMIT = 45000;

    // Counts the number of fish the contract owner has created.
    uint256 public promoCreatedCount;
    uint256 public gen0CreatedCount;

    // Direct sale is not live to start
    bool public directSalePaused = true;

    //determine the price for minting a new BitKoi gen0 egg
    uint256 public gen0PromoPrice = 5000000000000000000 wei;

    uint256 public currentGen0Cap = 100;

    // allow direct sales of gen0 eggs
    function pauseDirectSale() external onlyCLevel {
        directSalePaused = true;
    }

    // stop direct sales of gen0 eggs
    function unpauseDirectSale() external onlyCLevel {
        directSalePaused = false;
    }

    // set current cap for sale - this can be raised later so new sales can be started w/ limits
    function setCurrentGen0Cap(uint256 val) external onlyCEO {
        currentGen0Cap = val;
    }

    // @dev Updates the minimum payment required for calling mintGen0Egg(). Can only
    ///  be called by the CEO address.
    function setGen0PromoPrice(uint256 val) external onlyCEO {
        gen0PromoPrice = val;
    }

    function mintGen0Egg(address _owner) external payable {
        require (!directSalePaused);
        require (msg.value >= gen0PromoPrice);
        require (gen0CreatedCount < currentGen0Cap);
        require (gen0CreatedCount < GEN0_EGG_CREATION_LIMIT);

        //transfer the sale price less the pond cut to the CFO contract
        payable(address(cfoAddress)).transfer(msg.value);

        address bitKoiOwner = _owner;

        gen0CreatedCount++;

        _createBitKoi(0, 0, 0, 0, bitKoiOwner);

    }

    /// @dev we can create promo fish, up to a limit. Only callable by COO
    /// @param _genes the encoded genes of the fish to be created, any value is accepted
    /// @param _owner the future owner of the created fish. Default to contract COO
    function createPromoFish(uint256 _genes, address _owner) external onlyCOO {
        address bitKoiOwner = _owner;

        if (bitKoiOwner == address(0)) {
             bitKoiOwner = cooAddress;
        }

        require(promoCreatedCount < PROMO_CREATION_LIMIT);

        promoCreatedCount++;
        _createBitKoi(0, 0, 0, _genes, bitKoiOwner);
    }

}

contract BitKoiCore is BitKoiMinting {
    constructor(address _proxyRegistryAddress) ERC721Tradable("BitKoi", "BITKOI", _proxyRegistryAddress) {
        // Starts paused.
        paused = true;

        // the creator of the contract is the initial CEO
        ceoAddress = msg.sender;

        // the creator of the contract is also the initial COO
        cooAddress = msg.sender;

        // the creator of the contract is also the initial COO
        cfoAddress = msg.sender;

        //start with an initial fish
        _createBitKoi(0, 0, 0, type(uint256).max, address(this));

    }

    string baseURI = "https://www.bitkoi.co/api/nft/";
    string contractMainURI = "https://www.bitkoi.co";

    function baseTokenURI() public view returns (string memory) {
        return baseURI;
    }

    function setBaseTokenURI(string memory _newBaseURI) public onlyCEO {
        baseURI = _newBaseURI;
    }

    function setContractURI(string memory _newContractURI) public onlyCEO {
        contractMainURI = _newContractURI;
    }

    function tokenURI(uint256 _tokenId) override public view returns (string memory) {
        return string(abi.encodePacked(baseTokenURI(), Strings.toString(_tokenId)));
    }

    function contractURI() public view returns (string memory) {
        return contractMainURI;
    }

    function unpause() override public onlyCEO whenPaused {
        require(address(bitKoiTraits) != address(0));

        // Actually unpause the contract.
        super.unpause();
    }

    /// @notice Returns all the relevant information about a specific fish.
    /// @param _id The ID of the fish we're looking up
    function getBitKoi(uint256 _id)
        external
        view
        returns (
        bool isReady,
        uint256 cooldownIndex,
        uint256 nextActionAt,
        uint256 spawnTime,
        uint256 parent1Id,
        uint256 parent2Id,
        uint256 generation,
        uint256 cooldownEndBlock,
        uint256 genes
    ) {
        BitKoi storage fish = bitKoi[_id];
        isReady = (fish.cooldownEndBlock <= block.number);
        cooldownIndex = uint256(fish.cooldownIndex);
        nextActionAt = uint256(fish.cooldownEndBlock);
        spawnTime = uint256(fish.spawnTime);
        parent1Id = uint256(fish.parent1Id);
        parent2Id = uint256(fish.parent2Id);
        generation = uint256(fish.generation);
        cooldownEndBlock = uint256(fish.cooldownEndBlock);
        genes = fish.genes;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_proxyRegistryAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"AuctionCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sellerId","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endingPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startedAt","type":"uint256"}],"name":"AuctionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalPrice","type":"uint256"},{"indexed":false,"internalType":"address","name":"winner","type":"address"}],"name":"AuctionSuccessful","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"newFishId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"parent1Id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"parent2Id","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"cooldownEndBlock","type":"uint64"}],"name":"BreedingSuccessful","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"fishId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"genes","type":"uint256"}],"name":"Hatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"koiFishId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"parent1Id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"parent2Id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"genes","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"generation","type":"uint16"},{"indexed":false,"internalType":"uint64","name":"timestamp","type":"uint64"}],"name":"Spawn","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":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GEN0_EGG_CREATION_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROMO_CREATION_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[],"name":"averageGen0SalePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"bid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"bitKoiTraits","outputs":[{"internalType":"contract BitKoiTraitInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"breedFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_parent1Id","type":"uint256"},{"internalType":"uint256","name":"_parent2Id","type":"uint256"}],"name":"breedWith","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_parent1Id","type":"uint256"},{"internalType":"uint256","name":"_parent2Id","type":"uint256"}],"name":"canBreedWith","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"cancelAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"cancelAuctionWhenPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ceoAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cfoAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cooAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"cooldowns","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_startingPrice","type":"uint256"},{"internalType":"uint256","name":"_endingPrice","type":"uint256"},{"internalType":"uint256","name":"_duration","type":"uint256"},{"internalType":"address","name":"_seller","type":"address"}],"name":"createAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_genes","type":"uint256"},{"internalType":"address","name":"_owner","type":"address"}],"name":"createPromoFish","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentGen0Cap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"directSalePaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"gen0CreatedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gen0PromoPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gen0SaleCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getAuction","outputs":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"startingPrice","type":"uint256"},{"internalType":"uint256","name":"endingPrice","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"startedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getBitKoi","outputs":[{"internalType":"bool","name":"isReady","type":"bool"},{"internalType":"uint256","name":"cooldownIndex","type":"uint256"},{"internalType":"uint256","name":"nextActionAt","type":"uint256"},{"internalType":"uint256","name":"spawnTime","type":"uint256"},{"internalType":"uint256","name":"parent1Id","type":"uint256"},{"internalType":"uint256","name":"parent2Id","type":"uint256"},{"internalType":"uint256","name":"generation","type":"uint256"},{"internalType":"uint256","name":"cooldownEndBlock","type":"uint256"},{"internalType":"uint256","name":"genes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getCurrentPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hatchFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fishId","type":"uint256"},{"internalType":"uint256","name":"_geneSet1","type":"uint256"},{"internalType":"uint256","name":"_geneSet2","type":"uint256"}],"name":"hatchFish","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_koiId","type":"uint256"}],"name":"isReadyToBreed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_koiId","type":"uint256"}],"name":"isReadyToHatch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastGen0SalePrices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"mintGen0Egg","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerCut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseDirectSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"promoCreatedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[],"name":"secondsPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"setBaseTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setBitKoiTraitAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"name":"setBreedFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newCEO","type":"address"}],"name":"setCEO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newCFO","type":"address"}],"name":"setCFO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newCOO","type":"address"}],"name":"setCOO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newContractURI","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"name":"setCurrentGen0Cap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"name":"setGen0PromoPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"val","type":"uint256"}],"name":"setHatchFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ownerCut","type":"uint256"}],"name":"setOwnerCut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"secs","type":"uint256"}],"name":"setSecondsPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"ownerTokens","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transfer","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":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseDirectSale","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6002805460ff60a01b19169055600d805460ff191690556000601255610240604052603c6080908152607860a05261012c60c05261025860e05261070861010052610e1061012052611c2061014052613840610160526170806101805261e1006101a052620151806101c0526202a3006101e052620546006102005262093a80610220526200009390601390600e62000cc6565b50600f6015556000601a819055601b5560fa6023556027805460ff19166001179055674563918244f40000602855606460295560408051808201909152601e8082527f68747470733a2f2f7777772e6269746b6f692e636f2f6170692f6e66742f000060209092019182526200010c91602a9162000d69565b506040805180820190915260158082527f68747470733a2f2f7777772e6269746b6f692e636f000000000000000000000060209092019182526200015391602b9162000d69565b503480156200016157600080fd5b5060405162005a1b38038062005a1b833981016040819052620001849162000dfd565b604051806040016040528060068152602001654269744b6f6960d01b815250604051806040016040528060068152602001654249544b4f4960d01b8152508282828160039080519060200190620001dd92919062000d69565b508051620001f390600490602084019062000d69565b505050620002106200020a6200029060201b60201c565b620002ac565b601180546001600160a01b0319166001600160a01b0383161790556200023683620002fe565b505060028054600080546001600160a01b03199081163390811783556001600160a81b03199093168317600160a01b179093556001805490931690911790915562000288915080806000193062000363565b505062000f4d565b6000620002a7620005f860201b6200258e1760201c565b905090565b601080546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600d5460ff1615620003485760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b60448201526064015b60405180910390fd5b620003538162000657565b50600d805460ff19166001179055565b60008563ffffffff1686146200037857600080fd5b8463ffffffff1685146200038b57600080fd5b8361ffff1684146200039c57600080fd5b6000620003ab60028662000e73565b9050600d8161ffff161115620003bf5750600d5b6040805160e0810182528581526001600160401b0342811660208301908152600093830184815263ffffffff808d16606086019081528c82166080870190815261ffff808a1660a089019081528e821660c08a01908152601680546001810182559b52895160028c027fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428981019190915597517fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428a9098018054975195519451925191518416600160d01b0261ffff60d01b1992909416600160c01b029190911663ffffffff60c01b19928716600160a01b0263ffffffff60a01b19958816600160801b0295909516600160801b600160c01b0319968b1668010000000000000000026001600160801b031990991699909a169890981796909617939093169690961717169290921792909217909155909190811681146200051e57600080fd5b6200052a8582620006f9565b6060808301516080808501518551604080516001600160a01b038c1681526020810188905263ffffffff95861691810191909152919093169381019390935282015261ffff881660a08201526001600160401b03421660c08201527f9bf9fe90189516a96fd2554df7e10f0e2e5d2f38f76040e4e8b55d5dbf8868469060e00160405180910390a1600060168281548110620005ca57620005ca62000f37565b90600052602060002090600202019050620005eb816200075e60201b60201c565b5098975050505050505050565b6000333014156200065157600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b03169150620006549050565b50335b90565b6040518060800160405280604f8152602001620059cc604f9139805160209182012082519282019290922060408051808201825260018152603160f81b90840152805180840194909452838101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608401523060808401524660a0808501919091528151808503909101815260c090930190528151910120600e55565b6200070582826200084e565b6001600160a01b03821660009081526018602052604081208054916200072b8362000eed565b9091555050600090815260176020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6015546001820154439190601390600160c01b900461ffff16600e81106200078a576200078a62000f37565b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16620007b8919062000e73565b620007c4919062000e58565b600182018054600160401b600160801b031916680100000000000000006001600160401b0393909316929092029190911790819055600d600160c01b90910461ffff1610156200084b576001818101805460189062000830908490600160c01b900461ffff1662000e2f565b92506101000a81548161ffff021916908361ffff1602179055505b50565b6001600160a01b038216620008a65760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016200033f565b6000818152600560205260409020546001600160a01b0316156200090d5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016200033f565b6200091b60008383620009a4565b6001600160a01b03821660009081526006602052604081208054600192906200094690849062000e58565b909155505060008181526005602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b620009bc83838362000a5a60201b620010781760201c565b6001600160a01b03831662000a1a5762000a1481600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b62000a40565b816001600160a01b0316836001600160a01b03161462000a405762000a40838262000a85565b6001600160a01b03821662000a5f5762000a5a8162000b32565b505050565b826001600160a01b0316826001600160a01b03161462000a5a5762000a5a828262000bec565b6000600162000a9f8462000c3d60201b620025eb1760201c565b62000aab919062000e96565b6000838152600a602052604090205490915080821462000aff576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b5460009062000b469060019062000e96565b6000838152600c6020526040812054600b805493945090928490811062000b715762000b7162000f37565b9060005260206000200154905080600b838154811062000b955762000b9562000f37565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b80548062000bd05762000bd062000f21565b6001900381819060005260206000200160009055905550505050565b600062000c048362000c3d60201b620025eb1760201c565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b60006001600160a01b03821662000caa5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b60648201526084016200033f565b506001600160a01b031660009081526006602052604090205490565b60028301918390821562000d575791602002820160005b8382111562000d2357835183826101000a81548163ffffffff021916908363ffffffff160217905550926020019260040160208160030104928301926001030262000cdd565b801562000d555782816101000a81549063ffffffff021916905560040160208160030104928301926001030262000d23565b505b5062000d6592915062000de6565b5090565b82805462000d779062000eb0565b90600052602060002090601f01602090048101928262000d9b576000855562000d57565b82601f1062000db657805160ff191683800117855562000d57565b8280016001018555821562000d57579182015b8281111562000d5757825182559160200191906001019062000dc9565b5b8082111562000d65576000815560010162000de7565b60006020828403121562000e1057600080fd5b81516001600160a01b038116811462000e2857600080fd5b9392505050565b600061ffff80831681851680830382111562000e4f5762000e4f62000f0b565b01949350505050565b6000821982111562000e6e5762000e6e62000f0b565b500190565b60008262000e9157634e487b7160e01b600052601260045260246000fd5b500490565b60008282101562000eab5762000eab62000f0b565b500390565b600181811c9082168062000ec557607f821691505b6020821081141562000ee757634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141562000f045762000f0462000f0b565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b614a6f8062000f5d6000396000f3fe60806040526004361061045d5760003560e01c80637004fb841161023f578063a9059cbb11610139578063defb9584116100b6578063f1ca94101161007a578063f1ca941014610d56578063f2fde38b14610d6c578063fab620d014610d8c578063fc537fd614610dac578063fd03082714610dc257600080fd5b8063defb958414610c90578063e8a3d48514610ca6578063e985e9c514610cbb578063eac9d94c14610cdb578063f1c1395c14610cf057600080fd5b8063d3e6f49f116100fd578063d3e6f49f14610c10578063d547cfb714610c30578063d71b3cee14610c45578063d922341114610c5b578063dd02289214610c7057600080fd5b8063a9059cbb14610b70578063b047fb5014610b90578063b88d4fde14610bb0578063c55d0f5614610bd0578063c87b56dd14610bf057600080fd5b80638462151c116101c7578063938e3d7b1161018b578063938e3d7b14610ac657806395d89b4114610ae657806396b5a75514610afb5780639d6fac6f14610b1b578063a22cb46514610b5057600080fd5b80638462151c14610a25578063878eb36814610a525780638a98a9cc14610a725780638da5cb5b14610a88578063934fedf114610aa657600080fd5b806378bd79351161020e57806378bd7935146109725780637a7d4937146109c45780637c209688146109da57806383b5ff8b146109fa5780638456cb5914610a1057600080fd5b80637004fb841461090a57806370a082311461091d578063715018a61461093d578063757de5731461095257600080fd5b80632ba73c151161035b578063484eccb4116102d85780635c975abb1161029c5780635c975abb1461088d5780635dbd1f58146108ae5780636352211e146108c45780636527c46b146108e457806367d1d348146108f757600080fd5b8063484eccb4146107ed5780634e0a33791461080d5780634f6ccce71461082d5780634f8c79f81461084d5780635663896e1461086d57600080fd5b80633408e4701161031f5780633408e470146107725780633f4ba83a1461078557806342842e0e1461079a578063454a2ab3146107ba57806346d22c70146107cd57600080fd5b80632ba73c15146106c75780632d0335ab146106e75780632d3f81441461071d5780632f745c591461073257806330176e131461075257600080fd5b80630c53c51c116103e957806320379ee5116103ad57806320379ee514610638578063207269ea1461064d57806323b872dd1461066757806327d7874c1461068757806327ebe40a146106a757600080fd5b80630c53c51c146105ad5780630f7e5970146105c057806318160ddd146105ed5780631817d87e146106025780631d94885c1461061857600080fd5b806305e455461161043057806305e455461461051557806306fdde031461052b578063081812fc1461054d578063095ea7b31461056d5780630a0f81681461058d57600080fd5b806301ffc9a7146104625780630480329c1461049757806304c4ef20146104b95780630519ce79146104dd575b600080fd5b34801561046e57600080fd5b5061048261047d3660046142bb565b610de2565b60405190151581526020015b60405180910390f35b3480156104a357600080fd5b506104b76104b236600461435a565b610e0d565b005b3480156104c557600080fd5b506104cf61afc881565b60405190815260200161048e565b3480156104e957600080fd5b506001546104fd906001600160a01b031681565b6040516001600160a01b03909116815260200161048e565b34801561052157600080fd5b506104cf60255481565b34801561053757600080fd5b50610540610e29565b60405161048e9190614599565b34801561055957600080fd5b506104fd61056836600461435a565b610ebb565b34801561057957600080fd5b506104b7610588366004614272565b610f55565b34801561059957600080fd5b506000546104fd906001600160a01b031681565b6105406105bb3660046141f5565b61107d565b3480156105cc57600080fd5b50610540604051806040016040528060018152602001603160f81b81525081565b3480156105f957600080fd5b50600b546104cf565b34801561060e57600080fd5b506104cf601a5481565b34801561062457600080fd5b506104b761063336600461435a565b611267565b34801561064457600080fd5b50600e546104cf565b34801561065957600080fd5b506027546104829060ff1681565b34801561067357600080fd5b506104b761068236600461411b565b611283565b34801561069357600080fd5b506104b76106a23660046140c5565b6112bb565b3480156106b357600080fd5b506104b76106c23660046143ff565b611307565b3480156106d357600080fd5b506104b76106e23660046140c5565b6113f9565b3480156106f357600080fd5b506104cf6107023660046140c5565b6001600160a01b03166000908152600f602052604090205490565b34801561072957600080fd5b506104b7611445565b34801561073e57600080fd5b506104cf61074d366004614272565b611492565b34801561075e57600080fd5b506104b761076d366004614312565b611528565b34801561077e57600080fd5b50466104cf565b34801561079157600080fd5b506104b7611556565b3480156107a657600080fd5b506104b76107b536600461411b565b6115a2565b6104b76107c836600461435a565b6115bd565b3480156107d957600080fd5b506104826107e83660046143b1565b61164f565b3480156107f957600080fd5b506104cf61080836600461435a565b6116c9565b34801561081957600080fd5b506104b76108283660046140c5565b6116e0565b34801561083957600080fd5b506104cf61084836600461435a565b61172c565b34801561085957600080fd5b506104b761086836600461435a565b6117bf565b34801561087957600080fd5b506104b761088836600461435a565b6117db565b34801561089957600080fd5b5060025461048290600160a01b900460ff1681565b3480156108ba57600080fd5b506104cf60295481565b3480156108d057600080fd5b506104fd6108df36600461435a565b611835565b6104b76108f23660046140c5565b61185c565b6104b76109053660046143d3565b6118fa565b6104b76109183660046143b1565b61193e565b34801561092957600080fd5b506104cf6109383660046140c5565b611a4e565b34801561094957600080fd5b506104b7611a92565b34801561095e57600080fd5b506104b761096d36600461435a565b611ae5565b34801561097e57600080fd5b5061099261098d36600461435a565b611b10565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a00161048e565b3480156109d057600080fd5b506104cf60155481565b3480156109e657600080fd5b506104826109f536600461435a565b611b94565b348015610a0657600080fd5b506104cf60235481565b348015610a1c57600080fd5b506104b7611bab565b348015610a3157600080fd5b50610a45610a403660046140c5565b611c18565b60405161048e9190614555565b348015610a5e57600080fd5b506104b7610a6d36600461435a565b611d12565b348015610a7e57600080fd5b506104cf601d5481565b348015610a9457600080fd5b506010546001600160a01b03166104fd565b348015610ab257600080fd5b506104b7610ac136600461435a565b611da6565b348015610ad257600080fd5b506104b7610ae1366004614312565b611dc2565b348015610af257600080fd5b50610540611dec565b348015610b0757600080fd5b506104b7610b1636600461435a565b611dfb565b348015610b2757600080fd5b50610b3b610b3636600461435a565b611e47565b60405163ffffffff909116815260200161048e565b348015610b5c57600080fd5b506104b7610b6b3660046141c7565b611e77565b348015610b7c57600080fd5b506104b7610b8b366004614272565b611f79565b348015610b9c57600080fd5b506002546104fd906001600160a01b031681565b348015610bbc57600080fd5b506104b7610bcb36600461415c565b611fd7565b348015610bdc57600080fd5b506104cf610beb36600461435a565b612016565b348015610bfc57600080fd5b50610540610c0b36600461435a565b612052565b348015610c1c57600080fd5b50610482610c2b36600461435a565b61208c565b348015610c3c57600080fd5b506105406120e0565b348015610c5157600080fd5b506104cf60285481565b348015610c6757600080fd5b506104b76120ef565b348015610c7c57600080fd5b506104b7610c8b3660046140c5565b61213f565b348015610c9c57600080fd5b506104cf61138881565b348015610cb257600080fd5b506105406121f8565b348015610cc757600080fd5b50610482610cd63660046140e2565b612207565b348015610ce757600080fd5b506104cf6122d7565b348015610cfc57600080fd5b50610d10610d0b36600461435a565b61232a565b604080519915158a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e08301526101008201526101200161048e565b348015610d6257600080fd5b506104cf60265481565b348015610d7857600080fd5b506104b7610d873660046140c5565b61246c565b348015610d9857600080fd5b506104b7610da736600461438c565b612526565b348015610db857600080fd5b506104cf601b5481565b348015610dce57600080fd5b50601c546104fd906001600160a01b031681565b60006001600160e01b0319821663780e9d6360e01b1480610e075750610e078261262f565b92915050565b6000546001600160a01b03163314610e2457600080fd5b602955565b606060038054610e38906148eb565b80601f0160208091040260200160405190810160405280929190818152602001828054610e64906148eb565b8015610eb15780601f10610e8657610100808354040283529160200191610eb1565b820191906000526020600020905b815481529060010190602001808311610e9457829003601f168201915b5050505050905090565b6000818152600560205260408120546001600160a01b0316610f395760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600760205260409020546001600160a01b031690565b6000610f608261267f565b9050806001600160a01b0316836001600160a01b03161415610fce5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610f30565b806001600160a01b0316610fe06126f6565b6001600160a01b03161480610ffc5750610ffc81610cd66126f6565b61106e5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610f30565b6110788383612705565b505050565b60408051606081810183526001600160a01b0388166000818152600f6020908152908590205484528301529181018690526110bb8782878787612773565b6111115760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610f30565b6001600160a01b0387166000908152600f6020526040902054611135906001612863565b6001600160a01b0388166000908152600f60205260409081902091909155517f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b9061118590899033908a906144ec565b60405180910390a1600080306001600160a01b0316888a6040516020016111ad929190614486565b60408051601f19818403018152908290526111c79161446a565b6000604051808303816000865af19150503d8060008114611204576040519150601f19603f3d011682016040523d82523d6000602084013e611209565b606091505b50915091508161125b5760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610f30565b98975050505050505050565b6000546001600160a01b0316331461127e57600080fd5b602855565b61129461128e6126f6565b8261286f565b6112b05760405162461bcd60e51b8152600401610f309061467d565b61107883838361293e565b6000546001600160a01b031633146112d257600080fd5b6001600160a01b0381166112e557600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600254600160a01b900460ff161561131e57600080fd5b836001600160801b0316841461133357600080fd5b826001600160801b0316831461134857600080fd5b816001600160401b0316821461135d57600080fd5b8284101561136a57600080fd5b6000858152601760205260409020546001600160a01b0316331461138d57600080fd5b60006040518060a00160405280836001600160a01b03168152602001866001600160801b03168152602001856001600160801b03168152602001846001600160401b03168152602001426001600160401b031681525090506113f182878342612aef565b505050505050565b6000546001600160a01b0316331461141057600080fd5b6001600160a01b03811661142357600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b031633148061146857506000546001600160a01b031633145b8061147d57506001546001600160a01b031633145b61148657600080fd5b6027805460ff19169055565b600061149d836125eb565b82106114ff5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610f30565b506001600160a01b03919091166000908152600960209081526040808320938352929052205490565b6000546001600160a01b0316331461153f57600080fd5b805161155290602a906020840190613f97565b5050565b6000546001600160a01b0316331461156d57600080fd5b600254600160a01b900460ff1661158357600080fd5b601c546001600160a01b031661159857600080fd5b6115a0612bd7565b565b61107883838360405180602001604052806000815250611fd7565b600254600160a01b900460ff16156115d457600080fd5b6000818152602460205260408120546001600160a01b0316906115f78334612c13565b90506001600160a01b0382163014156116445780601e6005601d5461161c919061493b565b6005811061162c5761162c614991565b0155601d805490600061163e83614920565b91905055505b61107882338561293e565b600080831161165d57600080fd5b6000821161166a57600080fd5b60006016848154811061167f5761167f614991565b906000526020600020906002020190506000601684815481106116a4576116a4614991565b906000526020600020906002020190506116c082868387612d89565b95945050505050565b601e81600581106116d957600080fd5b0154905081565b6000546001600160a01b031633146116f757600080fd5b6001600160a01b03811661170a57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000611737600b5490565b821061179a5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610f30565b600b82815481106117ad576117ad614991565b90600052602060002001549050919050565b6000546001600160a01b031633146117d657600080fd5b601b55565b6002546001600160a01b03163314806117fe57506000546001600160a01b031633145b8061181357506001546001600160a01b031633145b61181c57600080fd5b60135463ffffffff16811061183057600080fd5b601555565b6000818152601760205260409020546001600160a01b03168061185757600080fd5b919050565b60275460ff161561186c57600080fd5b60285434101561187b57600080fd5b6029546026541061188b57600080fd5b61afc86026541061189b57600080fd5b6001546040516001600160a01b03909116903480156108fc02916000818181858888f193505050501580156118d4573d6000803e3d6000fd5b5060268054829160006118e683614920565b919050555061107860008060008085612f20565b600254600160a01b900460ff161561191157600080fd5b601b5434101561192057600080fd5b61192a338461319d565b61193357600080fd5b6110788383836131c3565b600254600160a01b900460ff161561195557600080fd5b601a5434101561196457600080fd5b61196e338361319d565b61197757600080fd5b611981338261319d565b61198a57600080fd5b60006016838154811061199f5761199f614991565b906000526020600020906002020190506119d081600101546001600160401b03438116600160401b90920416111590565b6119d957600080fd5b6000601683815481106119ee576119ee614991565b90600052602060002090600202019050611a1f81600101546001600160401b03438116600160401b90920416111590565b611a2857600080fd5b611a3481848487612d89565b611a3d57600080fd5b611a47848461344a565b5050505050565b60006001600160a01b038216611a765760405162461bcd60e51b8152600401610f30906145fe565b506001600160a01b031660009081526018602052604090205490565b611a9a6126f6565b6001600160a01b0316611ab56010546001600160a01b031690565b6001600160a01b031614611adb5760405162461bcd60e51b8152600401610f3090614648565b6115a060006135dc565b6000546001600160a01b03163314611afc57600080fd5b612710811115611b0b57600080fd5b602355565b600081815260246020526040812060028101548291829182918291600160401b90046001600160401b0316611b4457600080fd5b805460018201546002909201546001600160a01b03909116986001600160801b038084169950600160801b90930490921696506001600160401b038082169650600160401b909104169350915050565b6000808211611ba257600080fd5b610e078261362e565b6002546001600160a01b0316331480611bce57506000546001600160a01b031633145b80611be357506001546001600160a01b031633145b611bec57600080fd5b600254600160a01b900460ff1615611c0357600080fd5b6002805460ff60a01b1916600160a01b179055565b60606000611c2583611a4e565b905080611c42575050604080516000815260208101909152919050565b6000816001600160401b03811115611c5c57611c5c6149a7565b604051908082528060200260200182016040528015611c85578160200160208202803683370190505b5090506000611c93600b5490565b9050600060015b828111611d01576000818152601760205260409020546001600160a01b0388811691161415611cef5780848381518110611cd657611cd6614991565b602090810291909101015281611ceb81614920565b9250505b80611cf981614920565b915050611c9a565b509195945050505050565b50919050565b600254600160a01b900460ff16611d2857600080fd5b611d306126f6565b6001600160a01b0316611d4b6010546001600160a01b031690565b6001600160a01b031614611d715760405162461bcd60e51b8152600401610f3090614648565b60008181526024602052604090206002810154600160401b90046001600160401b0316611d9d57600080fd5b61155282613675565b6000546001600160a01b03163314611dbd57600080fd5b601a55565b6000546001600160a01b03163314611dd957600080fd5b805161155290602b906020840190613f97565b606060048054610e38906148eb565b60008181526024602052604090206002810154600160401b90046001600160401b0316611e2757600080fd5b80546001600160a01b0316338114611e3e57600080fd5b61107883613675565b601381600e8110611e5757600080fd5b60089182820401919006600402915054906101000a900463ffffffff1681565b611e7f6126f6565b6001600160a01b0316826001600160a01b03161415611ee05760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610f30565b8060086000611eed6126f6565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155611f316126f6565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611f6d911515815260200190565b60405180910390a35050565b600254600160a01b900460ff1615611f9057600080fd5b6001600160a01b038216611fa357600080fd5b6001600160a01b038216301415611fb957600080fd5b611fc3338261319d565b611fcc57600080fd5b61155233838361293e565b611fe8611fe26126f6565b8361286f565b6120045760405162461bcd60e51b8152600401610f309061467d565b612010848484846136b4565b50505050565b60008181526024602052604081206002810154600160401b90046001600160401b031661204257600080fd5b61204b816136e7565b9392505050565b606061205c6120e0565b6120658361375d565b6040516020016120769291906144bd565b6040516020818303038152906040529050919050565b600080821161209a57600080fd5b6000601683815481106120af576120af614991565b9060005260206000209060020201905061204b81600101546001600160401b03438116600160401b90920416111590565b6060602a8054610e38906148eb565b6002546001600160a01b031633148061211257506000546001600160a01b031633145b8061212757506001546001600160a01b031633145b61213057600080fd5b6027805460ff19166001179055565b6000546001600160a01b0316331461215657600080fd5b6000819050806001600160a01b031663f4bd77d76040518163ffffffff1660e01b815260040160206040518083038186803b15801561219457600080fd5b505afa1580156121a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121cc919061429e565b6121d557600080fd5b601c80546001600160a01b0319166001600160a01b039290921691909117905550565b6060602b8054610e38906148eb565b60115460405163c455279160e01b81526001600160a01b03848116600483015260009281169190841690829063c45527919060240160206040518083038186803b15801561225457600080fd5b505afa158015612268573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228c91906142f5565b6001600160a01b031614156122a5576001915050610e07565b6001600160a01b0380851660009081526008602090815260408083209387168352929052205460ff165b949350505050565b600080805b600581101561231857601e81600581106122f8576122f8614991565b0154612304908361472c565b91508061231081614920565b9150506122dc565b50612324600582614772565b91505090565b60008060008060008060008060008060168b8154811061234c5761234c614991565b90600052602060002090600202019050438160010160089054906101000a90046001600160401b03166001600160401b0316111599508060010160189054906101000a900461ffff1661ffff1698508060010160089054906101000a90046001600160401b03166001600160401b031697508060010160009054906101000a90046001600160401b03166001600160401b031696508060010160109054906101000a900463ffffffff1663ffffffff1695508060010160149054906101000a900463ffffffff1663ffffffff16945080600101601a9054906101000a900461ffff1661ffff1693508060010160089054906101000a90046001600160401b03166001600160401b0316925080600001549150509193959799909294969850565b6124746126f6565b6001600160a01b031661248f6010546001600160a01b031690565b6001600160a01b0316146124b55760405162461bcd60e51b8152600401610f3090614648565b6001600160a01b03811661251a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610f30565b612523816135dc565b50565b6002546001600160a01b0316331461253d57600080fd5b806001600160a01b03811661255a57506002546001600160a01b03165b6113886025541061256a57600080fd5b6025805490600061257a83614920565b919050555061201060008060008685612f20565b6000333014156125e557600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506125e89050565b50335b90565b60006001600160a01b0382166126135760405162461bcd60e51b8152600401610f30906145fe565b506001600160a01b031660009081526006602052604090205490565b60006001600160e01b031982166380ac58cd60e01b148061266057506001600160e01b03198216635b5e139f60e01b145b80610e0757506301ffc9a760e01b6001600160e01b0319831614610e07565b6000818152600560205260408120546001600160a01b031680610e075760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610f30565b600061270061258e565b905090565b600081815260076020526040902080546001600160a01b0319166001600160a01b038416908117909155819061273a8261267f565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006001600160a01b0386166127d95760405162461bcd60e51b815260206004820152602560248201527f4e61746976654d6574615472616e73616374696f6e3a20494e56414c49445f5360448201526424a3a722a960d91b6064820152608401610f30565b60016127ec6127e78761385a565b6138d7565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa15801561283a573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b031614905095945050505050565b600061204b828461472c565b6000818152600560205260408120546001600160a01b03166128e85760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610f30565b60006128f38361267f565b9050806001600160a01b0316846001600160a01b0316148061292e5750836001600160a01b031661292384610ebb565b6001600160a01b0316145b806122cf57506122cf8185612207565b826001600160a01b031661295182611835565b6001600160a01b0316146129b95760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610f30565b6001600160a01b038216612a1b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610f30565b6001600160a01b0382166000908152601860205260408120805491612a3f83614920565b90915550506001600160a01b0383166000908152601860205260408120805491612a68836148d4565b9190505550612a78838383613907565b600081815260176020526040812080546001600160a01b0319166001600160a01b038516179055612aa99082612705565b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600083815260246020908152604091829020845181546001600160a01b039182166001600160a01b031990911617825585830151868501516001600160801b03908116600160801b8102919092169081176001850155606080890151600290950180546080808c01516001600160401b03908116600160401b026001600160801b03199093169816978817919091179091558751948c1685529584018a905295830152938101939093529082015260a081018290527fabdd2430f9e10eb5db384c1218c42f980dd5fcda760a680a0d95ec506f0963cb9060c00160405180910390a150505050565b6000546001600160a01b03163314612bee57600080fd5b600254600160a01b900460ff16612c0457600080fd5b6002805460ff60a01b19169055565b60008281526024602052604081206002810154600160401b90046001600160401b0316612c3f57600080fd5b6000612c4a826136e7565b905080841015612c5957600080fd5b81546001600160a01b0316612c6d866139bf565b8115612d02576000612c7e836139f6565b90506000612c8c8285614869565b6001546040519192506001600160a01b03169083156108fc029084906000818181858888f19350505050158015612cc7573d6000803e3d6000fd5b506040516001600160a01b0384169082156108fc029083906000818181858888f19350505050158015612cfe573d6000803e3d6000fd5b5050505b6000612d0e8387614869565b604051909150339082156108fc029083906000818181858888f19350505050158015612d3e573d6000803e3d6000fd5b506040805188815260208101859052338183015290517f4fcc30d90a842164dd58501ab874a101a3749c3d4747139cefe7c876f4ccebd29181900360600190a1509095945050505050565b600081841415612d9b575060006122cf565b84541580612da857508254155b15612db5575060006122cf565b6001850154600160801b900463ffffffff16841480612de457506001850154600160a01b900463ffffffff1682145b15612df1575060006122cf565b6001830154600160801b900463ffffffff16841480612e2057506001830154600160a01b900463ffffffff1682145b15612e2d575060006122cf565b6001830154600160801b900463ffffffff161580612e5a57506001850154600160801b900463ffffffff16155b15612e67575060016122cf565b60018581015490840154600160801b9182900463ffffffff90811692909104161480612eb2575060018086015490840154600160801b900463ffffffff908116600160a01b90920416145b15612ebf575060006122cf565b60018581015490840154600160801b9182900463ffffffff90811692909104161480612f08575060018581015490840154600160a01b9182900463ffffffff9081169290910416145b15612f15575060006122cf565b506001949350505050565b60008563ffffffff168614612f3457600080fd5b8463ffffffff168514612f4657600080fd5b8361ffff168414612f5657600080fd5b6000612f63600286614772565b9050600d8161ffff161115612f765750600d5b6040805160e0810182528581526001600160401b0342811660208301908152600093830184815263ffffffff808d16606086019081528c82166080870190815261ffff808a1660a089019081528e821660c08a01908152601680546001810182559b52895160028c027fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428981019190915597517fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428a9098018054975195519451925191518416600160d01b0261ffff60d01b1992909416600160c01b029190911663ffffffff60c01b19928716600160a01b0263ffffffff60a01b19958816600160801b029590951667ffffffffffffffff60801b19968b16600160401b026001600160801b031990991699909a169890981796909617939093169690961717169290921792909217909155909190811681146130d057600080fd5b6130da8582613a13565b6060808301516080808501518551604080516001600160a01b038c1681526020810188905263ffffffff95861691810191909152919093169381019390935282015261ffff881660a08201526001600160401b03421660c08201527f9bf9fe90189516a96fd2554df7e10f0e2e5d2f38f76040e4e8b55d5dbf8868469060e00160405180910390a160006016828154811061317757613177614991565b9060005260206000209060020201905061319081613a74565b5098975050505050505050565b6000826001600160a01b03166131b283611835565b6001600160a01b0316149392505050565b6000601684815481106131d8576131d8614991565b90600052602060002090600202019050600060168260010160109054906101000a900463ffffffff1663ffffffff168154811061321757613217614991565b90600052602060002090600202019050600060168360010160149054906101000a900463ffffffff1663ffffffff168154811061325657613256614991565b60009182526020822060018601546002909202019250819063ffffffff600160801b909104161561328a578354915061328e565b8691505b6001850154600160a01b900463ffffffff16156132ad575081546132b0565b50845b60018401546001600160401b0316158015906132d8575060018301546001600160401b031615155b6132e157600080fd5b6132ea8861362e565b6132f357600080fd5b8454156132ff57600080fd5b601c546001868101546000926001600160a01b03169163851c9e2b91869186916133399190600160401b90046001600160401b0316614880565b6040516001600160e01b031960e086901b168152600481019390935260248301919091526001600160401b03166044820152606401602060405180830381600087803b15801561338857600080fd5b505af115801561339c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133c09190614373565b8087556001546040519192506001600160a01b0316903480156108fc02916000818181858888f193505050501580156133fd573d6000803e3d6000fd5b5060408051338152602081018b90529081018290527fb38ba9b1c21d14e92c6b24ace95218359ca7727f16a3e622617817dd9f38305c9060600160405180910390a1505050505050505050565b6000806016848154811061346057613460614991565b9060005260206000209060020201905060006016848154811061348557613485614991565b6000918252602090912060018085015460029093029091019081015490925061ffff600160d01b92839004811692909104168110156134d057506001810154600160d01b900461ffff165b60015460405134916001600160a01b03169082156108fc029083906000818181858888f1935050505015801561350a573d6000803e3d6000fd5b506000878152601760205260408120546001600160a01b031690613540898961353487600161470f565b61ffff16600086612f20565b905061354b86613a74565b61355485613a74565b60008981526017602090815260409182902054600189015483516001600160a01b0390921682529181018490529182018b9052606082018a9052600160401b90046001600160401b031660808201527f2257b42f89acde8ceea38e863df4cb1ed40dc32b9469264383a7577eeda61ac09060a00160405180910390a198975050505050505050565b601080546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000806016838154811061364457613644614991565b60009182526020909120600160029092020101546001600160401b03438116600160401b9092041611159392505050565b61367e816139bf565b6040518181527f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df9060200160405180910390a150565b6136bf84848461293e565b6136cb84848484613b5a565b6120105760405162461bcd60e51b8152600401610f30906145ac565b60028101546000908190600160401b90046001600160401b031642111561372a57600283015461372790600160401b90046001600160401b031642614869565b90505b6001830154600284015461204b916001600160801b0380821692600160801b90920416906001600160401b031684613c6b565b6060816137815750506040805180820190915260018152600360fc1b602082015290565b8160005b81156137ab578061379581614920565b91506137a49050600a83614772565b9150613785565b6000816001600160401b038111156137c5576137c56149a7565b6040519080825280601f01601f1916602001820160405280156137ef576020820181803683370190505b5090505b84156122cf57613804600183614869565b9150613811600a8661493b565b61381c90603061472c565b60f81b81838151811061383157613831614991565b60200101906001600160f81b031916908160001a905350613853600a86614772565b94506137f3565b60006040518060800160405280604381526020016149f760439139805160209182012083518483015160408087015180519086012090516138ba950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60006138e2600e5490565b60405161190160f01b60208201526022810191909152604281018390526062016138ba565b6001600160a01b0383166139625761395d81600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b613985565b816001600160a01b0316836001600160a01b031614613985576139858382613cb9565b6001600160a01b03821661399c5761107881613d56565b826001600160a01b0316826001600160a01b031614611078576110788282613e05565b600090815260246020526040812080546001600160a01b0319168155600181019190915560020180546001600160801b0319169055565b600061271060235483613a09919061480b565b610e079190614772565b613a1d8282613e49565b6001600160a01b0382166000908152601860205260408120805491613a4183614920565b9091555050600090815260176020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6015546001820154439190601390600160c01b900461ffff16600e8110613a9d57613a9d614991565b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16613ac99190614772565b613ad3919061472c565b6001820180546fffffffffffffffff00000000000000001916600160401b6001600160401b0393909316929092029190911790819055600d600160c01b90910461ffff1610156125235760018181018054601890613b3d908490600160c01b900461ffff1661470f565b92506101000a81548161ffff021916908361ffff16021790555050565b60006001600160a01b0384163b15613c6357836001600160a01b031663150b7a02613b836126f6565b8786866040518563ffffffff1660e01b8152600401613ba59493929190614518565b602060405180830381600087803b158015613bbf57600080fd5b505af1925050508015613bef575060408051601f3d908101601f19168201909252613bec918101906142d8565b60015b613c49573d808015613c1d576040519150601f19603f3d011682016040523d82523d6000602084013e613c22565b606091505b508051613c415760405162461bcd60e51b8152600401610f30906145ac565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506122cf565b5060016122cf565b6000828210613c7b5750826122cf565b6000613c87868661482a565b9050600084613c968584614786565b613ca09190614744565b90506000613cae82896146ce565b93506122cf92505050565b60006001613cc6846125eb565b613cd09190614869565b6000838152600a6020526040902054909150808214613d23576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b54600090613d6890600190614869565b6000838152600c6020526040812054600b8054939450909284908110613d9057613d90614991565b9060005260206000200154905080600b8381548110613db157613db1614991565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b805480613de957613de961497b565b6001900381819060005260206000200160009055905550505050565b6000613e10836125eb565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b6001600160a01b038216613e9f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610f30565b6000818152600560205260409020546001600160a01b031615613f045760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610f30565b613f1060008383613907565b6001600160a01b0382166000908152600660205260408120805460019290613f3990849061472c565b909155505060008181526005602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054613fa3906148eb565b90600052602060002090601f016020900481019282613fc5576000855561400b565b82601f10613fde57805160ff191683800117855561400b565b8280016001018555821561400b579182015b8281111561400b578251825591602001919060010190613ff0565b5061401792915061401b565b5090565b5b80821115614017576000815560010161401c565b60006001600160401b038084111561404a5761404a6149a7565b604051601f8501601f19908116603f01168101908282118183101715614072576140726149a7565b8160405280935085815286868601111561408b57600080fd5b858560208301376000602087830101525050509392505050565b600082601f8301126140b657600080fd5b61204b83833560208501614030565b6000602082840312156140d757600080fd5b813561204b816149bd565b600080604083850312156140f557600080fd5b8235614100816149bd565b91506020830135614110816149bd565b809150509250929050565b60008060006060848603121561413057600080fd5b833561413b816149bd565b9250602084013561414b816149bd565b929592945050506040919091013590565b6000806000806080858703121561417257600080fd5b843561417d816149bd565b9350602085013561418d816149bd565b92506040850135915060608501356001600160401b038111156141af57600080fd5b6141bb878288016140a5565b91505092959194509250565b600080604083850312156141da57600080fd5b82356141e5816149bd565b91506020830135614110816149d2565b600080600080600060a0868803121561420d57600080fd5b8535614218816149bd565b945060208601356001600160401b0381111561423357600080fd5b61423f888289016140a5565b9450506040860135925060608601359150608086013560ff8116811461426457600080fd5b809150509295509295909350565b6000806040838503121561428557600080fd5b8235614290816149bd565b946020939093013593505050565b6000602082840312156142b057600080fd5b815161204b816149d2565b6000602082840312156142cd57600080fd5b813561204b816149e0565b6000602082840312156142ea57600080fd5b815161204b816149e0565b60006020828403121561430757600080fd5b815161204b816149bd565b60006020828403121561432457600080fd5b81356001600160401b0381111561433a57600080fd5b8201601f8101841361434b57600080fd5b6122cf84823560208401614030565b60006020828403121561436c57600080fd5b5035919050565b60006020828403121561438557600080fd5b5051919050565b6000806040838503121561439f57600080fd5b823591506020830135614110816149bd565b600080604083850312156143c457600080fd5b50508035926020909101359150565b6000806000606084860312156143e857600080fd5b505081359360208301359350604090920135919050565b600080600080600060a0868803121561441757600080fd5b853594506020860135935060408601359250606086013591506080860135614264816149bd565b600081518084526144568160208601602086016148a8565b601f01601f19169290920160200192915050565b6000825161447c8184602087016148a8565b9190910192915050565b600083516144988184602088016148a8565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b600083516144cf8184602088016148a8565b8351908301906144e38183602088016148a8565b01949350505050565b6001600160a01b038481168252831660208201526060604082018190526000906116c09083018461443e565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061454b9083018461443e565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561458d57835183529284019291840191600101614571565b50909695505050505050565b60208152600061204b602083018461443e565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604082015269726f206164647265737360b01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b600080821280156001600160ff1b03849003851316156146f0576146f061494f565b600160ff1b83900384128116156147095761470961494f565b50500190565b600061ffff8083168185168083038211156144e3576144e361494f565b6000821982111561473f5761473f61494f565b500190565b60008261475357614753614965565b600160ff1b82146000198414161561476d5761476d61494f565b500590565b60008261478157614781614965565b500490565b60006001600160ff1b03818413828413808216868404861116156147ac576147ac61494f565b600160ff1b60008712828116878305891216156147cb576147cb61494f565b600087129250878205871284841616156147e7576147e761494f565b878505871281841616156147fd576147fd61494f565b505050929093029392505050565b60008160001904831182151516156148255761482561494f565b500290565b60008083128015600160ff1b8501841216156148485761484861494f565b6001600160ff1b03840183138116156148635761486361494f565b50500390565b60008282101561487b5761487b61494f565b500390565b60006001600160401b03838116908316818110156148a0576148a061494f565b039392505050565b60005b838110156148c35781810151838201526020016148ab565b838111156120105750506000910152565b6000816148e3576148e361494f565b506000190190565b600181811c908216806148ff57607f821691505b60208210811415611d0c57634e487b7160e01b600052602260045260246000fd5b60006000198214156149345761493461494f565b5060010190565b60008261494a5761494a614965565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461252357600080fd5b801515811461252357600080fd5b6001600160e01b03198116811461252357600080fdfe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529a264697066735822122070b45eda88a8feb483a94a2759c4a46b69cd8c0bbd18b3c970990c8b5985e22b64736f6c63430008070033454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c6164647265737320766572696679696e67436f6e74726163742c627974657333322073616c7429000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1

Deployed Bytecode

0x60806040526004361061045d5760003560e01c80637004fb841161023f578063a9059cbb11610139578063defb9584116100b6578063f1ca94101161007a578063f1ca941014610d56578063f2fde38b14610d6c578063fab620d014610d8c578063fc537fd614610dac578063fd03082714610dc257600080fd5b8063defb958414610c90578063e8a3d48514610ca6578063e985e9c514610cbb578063eac9d94c14610cdb578063f1c1395c14610cf057600080fd5b8063d3e6f49f116100fd578063d3e6f49f14610c10578063d547cfb714610c30578063d71b3cee14610c45578063d922341114610c5b578063dd02289214610c7057600080fd5b8063a9059cbb14610b70578063b047fb5014610b90578063b88d4fde14610bb0578063c55d0f5614610bd0578063c87b56dd14610bf057600080fd5b80638462151c116101c7578063938e3d7b1161018b578063938e3d7b14610ac657806395d89b4114610ae657806396b5a75514610afb5780639d6fac6f14610b1b578063a22cb46514610b5057600080fd5b80638462151c14610a25578063878eb36814610a525780638a98a9cc14610a725780638da5cb5b14610a88578063934fedf114610aa657600080fd5b806378bd79351161020e57806378bd7935146109725780637a7d4937146109c45780637c209688146109da57806383b5ff8b146109fa5780638456cb5914610a1057600080fd5b80637004fb841461090a57806370a082311461091d578063715018a61461093d578063757de5731461095257600080fd5b80632ba73c151161035b578063484eccb4116102d85780635c975abb1161029c5780635c975abb1461088d5780635dbd1f58146108ae5780636352211e146108c45780636527c46b146108e457806367d1d348146108f757600080fd5b8063484eccb4146107ed5780634e0a33791461080d5780634f6ccce71461082d5780634f8c79f81461084d5780635663896e1461086d57600080fd5b80633408e4701161031f5780633408e470146107725780633f4ba83a1461078557806342842e0e1461079a578063454a2ab3146107ba57806346d22c70146107cd57600080fd5b80632ba73c15146106c75780632d0335ab146106e75780632d3f81441461071d5780632f745c591461073257806330176e131461075257600080fd5b80630c53c51c116103e957806320379ee5116103ad57806320379ee514610638578063207269ea1461064d57806323b872dd1461066757806327d7874c1461068757806327ebe40a146106a757600080fd5b80630c53c51c146105ad5780630f7e5970146105c057806318160ddd146105ed5780631817d87e146106025780631d94885c1461061857600080fd5b806305e455461161043057806305e455461461051557806306fdde031461052b578063081812fc1461054d578063095ea7b31461056d5780630a0f81681461058d57600080fd5b806301ffc9a7146104625780630480329c1461049757806304c4ef20146104b95780630519ce79146104dd575b600080fd5b34801561046e57600080fd5b5061048261047d3660046142bb565b610de2565b60405190151581526020015b60405180910390f35b3480156104a357600080fd5b506104b76104b236600461435a565b610e0d565b005b3480156104c557600080fd5b506104cf61afc881565b60405190815260200161048e565b3480156104e957600080fd5b506001546104fd906001600160a01b031681565b6040516001600160a01b03909116815260200161048e565b34801561052157600080fd5b506104cf60255481565b34801561053757600080fd5b50610540610e29565b60405161048e9190614599565b34801561055957600080fd5b506104fd61056836600461435a565b610ebb565b34801561057957600080fd5b506104b7610588366004614272565b610f55565b34801561059957600080fd5b506000546104fd906001600160a01b031681565b6105406105bb3660046141f5565b61107d565b3480156105cc57600080fd5b50610540604051806040016040528060018152602001603160f81b81525081565b3480156105f957600080fd5b50600b546104cf565b34801561060e57600080fd5b506104cf601a5481565b34801561062457600080fd5b506104b761063336600461435a565b611267565b34801561064457600080fd5b50600e546104cf565b34801561065957600080fd5b506027546104829060ff1681565b34801561067357600080fd5b506104b761068236600461411b565b611283565b34801561069357600080fd5b506104b76106a23660046140c5565b6112bb565b3480156106b357600080fd5b506104b76106c23660046143ff565b611307565b3480156106d357600080fd5b506104b76106e23660046140c5565b6113f9565b3480156106f357600080fd5b506104cf6107023660046140c5565b6001600160a01b03166000908152600f602052604090205490565b34801561072957600080fd5b506104b7611445565b34801561073e57600080fd5b506104cf61074d366004614272565b611492565b34801561075e57600080fd5b506104b761076d366004614312565b611528565b34801561077e57600080fd5b50466104cf565b34801561079157600080fd5b506104b7611556565b3480156107a657600080fd5b506104b76107b536600461411b565b6115a2565b6104b76107c836600461435a565b6115bd565b3480156107d957600080fd5b506104826107e83660046143b1565b61164f565b3480156107f957600080fd5b506104cf61080836600461435a565b6116c9565b34801561081957600080fd5b506104b76108283660046140c5565b6116e0565b34801561083957600080fd5b506104cf61084836600461435a565b61172c565b34801561085957600080fd5b506104b761086836600461435a565b6117bf565b34801561087957600080fd5b506104b761088836600461435a565b6117db565b34801561089957600080fd5b5060025461048290600160a01b900460ff1681565b3480156108ba57600080fd5b506104cf60295481565b3480156108d057600080fd5b506104fd6108df36600461435a565b611835565b6104b76108f23660046140c5565b61185c565b6104b76109053660046143d3565b6118fa565b6104b76109183660046143b1565b61193e565b34801561092957600080fd5b506104cf6109383660046140c5565b611a4e565b34801561094957600080fd5b506104b7611a92565b34801561095e57600080fd5b506104b761096d36600461435a565b611ae5565b34801561097e57600080fd5b5061099261098d36600461435a565b611b10565b604080516001600160a01b0390961686526020860194909452928401919091526060830152608082015260a00161048e565b3480156109d057600080fd5b506104cf60155481565b3480156109e657600080fd5b506104826109f536600461435a565b611b94565b348015610a0657600080fd5b506104cf60235481565b348015610a1c57600080fd5b506104b7611bab565b348015610a3157600080fd5b50610a45610a403660046140c5565b611c18565b60405161048e9190614555565b348015610a5e57600080fd5b506104b7610a6d36600461435a565b611d12565b348015610a7e57600080fd5b506104cf601d5481565b348015610a9457600080fd5b506010546001600160a01b03166104fd565b348015610ab257600080fd5b506104b7610ac136600461435a565b611da6565b348015610ad257600080fd5b506104b7610ae1366004614312565b611dc2565b348015610af257600080fd5b50610540611dec565b348015610b0757600080fd5b506104b7610b1636600461435a565b611dfb565b348015610b2757600080fd5b50610b3b610b3636600461435a565b611e47565b60405163ffffffff909116815260200161048e565b348015610b5c57600080fd5b506104b7610b6b3660046141c7565b611e77565b348015610b7c57600080fd5b506104b7610b8b366004614272565b611f79565b348015610b9c57600080fd5b506002546104fd906001600160a01b031681565b348015610bbc57600080fd5b506104b7610bcb36600461415c565b611fd7565b348015610bdc57600080fd5b506104cf610beb36600461435a565b612016565b348015610bfc57600080fd5b50610540610c0b36600461435a565b612052565b348015610c1c57600080fd5b50610482610c2b36600461435a565b61208c565b348015610c3c57600080fd5b506105406120e0565b348015610c5157600080fd5b506104cf60285481565b348015610c6757600080fd5b506104b76120ef565b348015610c7c57600080fd5b506104b7610c8b3660046140c5565b61213f565b348015610c9c57600080fd5b506104cf61138881565b348015610cb257600080fd5b506105406121f8565b348015610cc757600080fd5b50610482610cd63660046140e2565b612207565b348015610ce757600080fd5b506104cf6122d7565b348015610cfc57600080fd5b50610d10610d0b36600461435a565b61232a565b604080519915158a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e08301526101008201526101200161048e565b348015610d6257600080fd5b506104cf60265481565b348015610d7857600080fd5b506104b7610d873660046140c5565b61246c565b348015610d9857600080fd5b506104b7610da736600461438c565b612526565b348015610db857600080fd5b506104cf601b5481565b348015610dce57600080fd5b50601c546104fd906001600160a01b031681565b60006001600160e01b0319821663780e9d6360e01b1480610e075750610e078261262f565b92915050565b6000546001600160a01b03163314610e2457600080fd5b602955565b606060038054610e38906148eb565b80601f0160208091040260200160405190810160405280929190818152602001828054610e64906148eb565b8015610eb15780601f10610e8657610100808354040283529160200191610eb1565b820191906000526020600020905b815481529060010190602001808311610e9457829003601f168201915b5050505050905090565b6000818152600560205260408120546001600160a01b0316610f395760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600760205260409020546001600160a01b031690565b6000610f608261267f565b9050806001600160a01b0316836001600160a01b03161415610fce5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610f30565b806001600160a01b0316610fe06126f6565b6001600160a01b03161480610ffc5750610ffc81610cd66126f6565b61106e5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610f30565b6110788383612705565b505050565b60408051606081810183526001600160a01b0388166000818152600f6020908152908590205484528301529181018690526110bb8782878787612773565b6111115760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610f30565b6001600160a01b0387166000908152600f6020526040902054611135906001612863565b6001600160a01b0388166000908152600f60205260409081902091909155517f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b9061118590899033908a906144ec565b60405180910390a1600080306001600160a01b0316888a6040516020016111ad929190614486565b60408051601f19818403018152908290526111c79161446a565b6000604051808303816000865af19150503d8060008114611204576040519150601f19603f3d011682016040523d82523d6000602084013e611209565b606091505b50915091508161125b5760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610f30565b98975050505050505050565b6000546001600160a01b0316331461127e57600080fd5b602855565b61129461128e6126f6565b8261286f565b6112b05760405162461bcd60e51b8152600401610f309061467d565b61107883838361293e565b6000546001600160a01b031633146112d257600080fd5b6001600160a01b0381166112e557600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600254600160a01b900460ff161561131e57600080fd5b836001600160801b0316841461133357600080fd5b826001600160801b0316831461134857600080fd5b816001600160401b0316821461135d57600080fd5b8284101561136a57600080fd5b6000858152601760205260409020546001600160a01b0316331461138d57600080fd5b60006040518060a00160405280836001600160a01b03168152602001866001600160801b03168152602001856001600160801b03168152602001846001600160401b03168152602001426001600160401b031681525090506113f182878342612aef565b505050505050565b6000546001600160a01b0316331461141057600080fd5b6001600160a01b03811661142357600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b031633148061146857506000546001600160a01b031633145b8061147d57506001546001600160a01b031633145b61148657600080fd5b6027805460ff19169055565b600061149d836125eb565b82106114ff5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610f30565b506001600160a01b03919091166000908152600960209081526040808320938352929052205490565b6000546001600160a01b0316331461153f57600080fd5b805161155290602a906020840190613f97565b5050565b6000546001600160a01b0316331461156d57600080fd5b600254600160a01b900460ff1661158357600080fd5b601c546001600160a01b031661159857600080fd5b6115a0612bd7565b565b61107883838360405180602001604052806000815250611fd7565b600254600160a01b900460ff16156115d457600080fd5b6000818152602460205260408120546001600160a01b0316906115f78334612c13565b90506001600160a01b0382163014156116445780601e6005601d5461161c919061493b565b6005811061162c5761162c614991565b0155601d805490600061163e83614920565b91905055505b61107882338561293e565b600080831161165d57600080fd5b6000821161166a57600080fd5b60006016848154811061167f5761167f614991565b906000526020600020906002020190506000601684815481106116a4576116a4614991565b906000526020600020906002020190506116c082868387612d89565b95945050505050565b601e81600581106116d957600080fd5b0154905081565b6000546001600160a01b031633146116f757600080fd5b6001600160a01b03811661170a57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000611737600b5490565b821061179a5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610f30565b600b82815481106117ad576117ad614991565b90600052602060002001549050919050565b6000546001600160a01b031633146117d657600080fd5b601b55565b6002546001600160a01b03163314806117fe57506000546001600160a01b031633145b8061181357506001546001600160a01b031633145b61181c57600080fd5b60135463ffffffff16811061183057600080fd5b601555565b6000818152601760205260409020546001600160a01b03168061185757600080fd5b919050565b60275460ff161561186c57600080fd5b60285434101561187b57600080fd5b6029546026541061188b57600080fd5b61afc86026541061189b57600080fd5b6001546040516001600160a01b03909116903480156108fc02916000818181858888f193505050501580156118d4573d6000803e3d6000fd5b5060268054829160006118e683614920565b919050555061107860008060008085612f20565b600254600160a01b900460ff161561191157600080fd5b601b5434101561192057600080fd5b61192a338461319d565b61193357600080fd5b6110788383836131c3565b600254600160a01b900460ff161561195557600080fd5b601a5434101561196457600080fd5b61196e338361319d565b61197757600080fd5b611981338261319d565b61198a57600080fd5b60006016838154811061199f5761199f614991565b906000526020600020906002020190506119d081600101546001600160401b03438116600160401b90920416111590565b6119d957600080fd5b6000601683815481106119ee576119ee614991565b90600052602060002090600202019050611a1f81600101546001600160401b03438116600160401b90920416111590565b611a2857600080fd5b611a3481848487612d89565b611a3d57600080fd5b611a47848461344a565b5050505050565b60006001600160a01b038216611a765760405162461bcd60e51b8152600401610f30906145fe565b506001600160a01b031660009081526018602052604090205490565b611a9a6126f6565b6001600160a01b0316611ab56010546001600160a01b031690565b6001600160a01b031614611adb5760405162461bcd60e51b8152600401610f3090614648565b6115a060006135dc565b6000546001600160a01b03163314611afc57600080fd5b612710811115611b0b57600080fd5b602355565b600081815260246020526040812060028101548291829182918291600160401b90046001600160401b0316611b4457600080fd5b805460018201546002909201546001600160a01b03909116986001600160801b038084169950600160801b90930490921696506001600160401b038082169650600160401b909104169350915050565b6000808211611ba257600080fd5b610e078261362e565b6002546001600160a01b0316331480611bce57506000546001600160a01b031633145b80611be357506001546001600160a01b031633145b611bec57600080fd5b600254600160a01b900460ff1615611c0357600080fd5b6002805460ff60a01b1916600160a01b179055565b60606000611c2583611a4e565b905080611c42575050604080516000815260208101909152919050565b6000816001600160401b03811115611c5c57611c5c6149a7565b604051908082528060200260200182016040528015611c85578160200160208202803683370190505b5090506000611c93600b5490565b9050600060015b828111611d01576000818152601760205260409020546001600160a01b0388811691161415611cef5780848381518110611cd657611cd6614991565b602090810291909101015281611ceb81614920565b9250505b80611cf981614920565b915050611c9a565b509195945050505050565b50919050565b600254600160a01b900460ff16611d2857600080fd5b611d306126f6565b6001600160a01b0316611d4b6010546001600160a01b031690565b6001600160a01b031614611d715760405162461bcd60e51b8152600401610f3090614648565b60008181526024602052604090206002810154600160401b90046001600160401b0316611d9d57600080fd5b61155282613675565b6000546001600160a01b03163314611dbd57600080fd5b601a55565b6000546001600160a01b03163314611dd957600080fd5b805161155290602b906020840190613f97565b606060048054610e38906148eb565b60008181526024602052604090206002810154600160401b90046001600160401b0316611e2757600080fd5b80546001600160a01b0316338114611e3e57600080fd5b61107883613675565b601381600e8110611e5757600080fd5b60089182820401919006600402915054906101000a900463ffffffff1681565b611e7f6126f6565b6001600160a01b0316826001600160a01b03161415611ee05760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610f30565b8060086000611eed6126f6565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155611f316126f6565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611f6d911515815260200190565b60405180910390a35050565b600254600160a01b900460ff1615611f9057600080fd5b6001600160a01b038216611fa357600080fd5b6001600160a01b038216301415611fb957600080fd5b611fc3338261319d565b611fcc57600080fd5b61155233838361293e565b611fe8611fe26126f6565b8361286f565b6120045760405162461bcd60e51b8152600401610f309061467d565b612010848484846136b4565b50505050565b60008181526024602052604081206002810154600160401b90046001600160401b031661204257600080fd5b61204b816136e7565b9392505050565b606061205c6120e0565b6120658361375d565b6040516020016120769291906144bd565b6040516020818303038152906040529050919050565b600080821161209a57600080fd5b6000601683815481106120af576120af614991565b9060005260206000209060020201905061204b81600101546001600160401b03438116600160401b90920416111590565b6060602a8054610e38906148eb565b6002546001600160a01b031633148061211257506000546001600160a01b031633145b8061212757506001546001600160a01b031633145b61213057600080fd5b6027805460ff19166001179055565b6000546001600160a01b0316331461215657600080fd5b6000819050806001600160a01b031663f4bd77d76040518163ffffffff1660e01b815260040160206040518083038186803b15801561219457600080fd5b505afa1580156121a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121cc919061429e565b6121d557600080fd5b601c80546001600160a01b0319166001600160a01b039290921691909117905550565b6060602b8054610e38906148eb565b60115460405163c455279160e01b81526001600160a01b03848116600483015260009281169190841690829063c45527919060240160206040518083038186803b15801561225457600080fd5b505afa158015612268573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228c91906142f5565b6001600160a01b031614156122a5576001915050610e07565b6001600160a01b0380851660009081526008602090815260408083209387168352929052205460ff165b949350505050565b600080805b600581101561231857601e81600581106122f8576122f8614991565b0154612304908361472c565b91508061231081614920565b9150506122dc565b50612324600582614772565b91505090565b60008060008060008060008060008060168b8154811061234c5761234c614991565b90600052602060002090600202019050438160010160089054906101000a90046001600160401b03166001600160401b0316111599508060010160189054906101000a900461ffff1661ffff1698508060010160089054906101000a90046001600160401b03166001600160401b031697508060010160009054906101000a90046001600160401b03166001600160401b031696508060010160109054906101000a900463ffffffff1663ffffffff1695508060010160149054906101000a900463ffffffff1663ffffffff16945080600101601a9054906101000a900461ffff1661ffff1693508060010160089054906101000a90046001600160401b03166001600160401b0316925080600001549150509193959799909294969850565b6124746126f6565b6001600160a01b031661248f6010546001600160a01b031690565b6001600160a01b0316146124b55760405162461bcd60e51b8152600401610f3090614648565b6001600160a01b03811661251a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610f30565b612523816135dc565b50565b6002546001600160a01b0316331461253d57600080fd5b806001600160a01b03811661255a57506002546001600160a01b03165b6113886025541061256a57600080fd5b6025805490600061257a83614920565b919050555061201060008060008685612f20565b6000333014156125e557600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506125e89050565b50335b90565b60006001600160a01b0382166126135760405162461bcd60e51b8152600401610f30906145fe565b506001600160a01b031660009081526006602052604090205490565b60006001600160e01b031982166380ac58cd60e01b148061266057506001600160e01b03198216635b5e139f60e01b145b80610e0757506301ffc9a760e01b6001600160e01b0319831614610e07565b6000818152600560205260408120546001600160a01b031680610e075760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610f30565b600061270061258e565b905090565b600081815260076020526040902080546001600160a01b0319166001600160a01b038416908117909155819061273a8261267f565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006001600160a01b0386166127d95760405162461bcd60e51b815260206004820152602560248201527f4e61746976654d6574615472616e73616374696f6e3a20494e56414c49445f5360448201526424a3a722a960d91b6064820152608401610f30565b60016127ec6127e78761385a565b6138d7565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa15801561283a573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b031614905095945050505050565b600061204b828461472c565b6000818152600560205260408120546001600160a01b03166128e85760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610f30565b60006128f38361267f565b9050806001600160a01b0316846001600160a01b0316148061292e5750836001600160a01b031661292384610ebb565b6001600160a01b0316145b806122cf57506122cf8185612207565b826001600160a01b031661295182611835565b6001600160a01b0316146129b95760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610f30565b6001600160a01b038216612a1b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610f30565b6001600160a01b0382166000908152601860205260408120805491612a3f83614920565b90915550506001600160a01b0383166000908152601860205260408120805491612a68836148d4565b9190505550612a78838383613907565b600081815260176020526040812080546001600160a01b0319166001600160a01b038516179055612aa99082612705565b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600083815260246020908152604091829020845181546001600160a01b039182166001600160a01b031990911617825585830151868501516001600160801b03908116600160801b8102919092169081176001850155606080890151600290950180546080808c01516001600160401b03908116600160401b026001600160801b03199093169816978817919091179091558751948c1685529584018a905295830152938101939093529082015260a081018290527fabdd2430f9e10eb5db384c1218c42f980dd5fcda760a680a0d95ec506f0963cb9060c00160405180910390a150505050565b6000546001600160a01b03163314612bee57600080fd5b600254600160a01b900460ff16612c0457600080fd5b6002805460ff60a01b19169055565b60008281526024602052604081206002810154600160401b90046001600160401b0316612c3f57600080fd5b6000612c4a826136e7565b905080841015612c5957600080fd5b81546001600160a01b0316612c6d866139bf565b8115612d02576000612c7e836139f6565b90506000612c8c8285614869565b6001546040519192506001600160a01b03169083156108fc029084906000818181858888f19350505050158015612cc7573d6000803e3d6000fd5b506040516001600160a01b0384169082156108fc029083906000818181858888f19350505050158015612cfe573d6000803e3d6000fd5b5050505b6000612d0e8387614869565b604051909150339082156108fc029083906000818181858888f19350505050158015612d3e573d6000803e3d6000fd5b506040805188815260208101859052338183015290517f4fcc30d90a842164dd58501ab874a101a3749c3d4747139cefe7c876f4ccebd29181900360600190a1509095945050505050565b600081841415612d9b575060006122cf565b84541580612da857508254155b15612db5575060006122cf565b6001850154600160801b900463ffffffff16841480612de457506001850154600160a01b900463ffffffff1682145b15612df1575060006122cf565b6001830154600160801b900463ffffffff16841480612e2057506001830154600160a01b900463ffffffff1682145b15612e2d575060006122cf565b6001830154600160801b900463ffffffff161580612e5a57506001850154600160801b900463ffffffff16155b15612e67575060016122cf565b60018581015490840154600160801b9182900463ffffffff90811692909104161480612eb2575060018086015490840154600160801b900463ffffffff908116600160a01b90920416145b15612ebf575060006122cf565b60018581015490840154600160801b9182900463ffffffff90811692909104161480612f08575060018581015490840154600160a01b9182900463ffffffff9081169290910416145b15612f15575060006122cf565b506001949350505050565b60008563ffffffff168614612f3457600080fd5b8463ffffffff168514612f4657600080fd5b8361ffff168414612f5657600080fd5b6000612f63600286614772565b9050600d8161ffff161115612f765750600d5b6040805160e0810182528581526001600160401b0342811660208301908152600093830184815263ffffffff808d16606086019081528c82166080870190815261ffff808a1660a089019081528e821660c08a01908152601680546001810182559b52895160028c027fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428981019190915597517fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428a9098018054975195519451925191518416600160d01b0261ffff60d01b1992909416600160c01b029190911663ffffffff60c01b19928716600160a01b0263ffffffff60a01b19958816600160801b029590951667ffffffffffffffff60801b19968b16600160401b026001600160801b031990991699909a169890981796909617939093169690961717169290921792909217909155909190811681146130d057600080fd5b6130da8582613a13565b6060808301516080808501518551604080516001600160a01b038c1681526020810188905263ffffffff95861691810191909152919093169381019390935282015261ffff881660a08201526001600160401b03421660c08201527f9bf9fe90189516a96fd2554df7e10f0e2e5d2f38f76040e4e8b55d5dbf8868469060e00160405180910390a160006016828154811061317757613177614991565b9060005260206000209060020201905061319081613a74565b5098975050505050505050565b6000826001600160a01b03166131b283611835565b6001600160a01b0316149392505050565b6000601684815481106131d8576131d8614991565b90600052602060002090600202019050600060168260010160109054906101000a900463ffffffff1663ffffffff168154811061321757613217614991565b90600052602060002090600202019050600060168360010160149054906101000a900463ffffffff1663ffffffff168154811061325657613256614991565b60009182526020822060018601546002909202019250819063ffffffff600160801b909104161561328a578354915061328e565b8691505b6001850154600160a01b900463ffffffff16156132ad575081546132b0565b50845b60018401546001600160401b0316158015906132d8575060018301546001600160401b031615155b6132e157600080fd5b6132ea8861362e565b6132f357600080fd5b8454156132ff57600080fd5b601c546001868101546000926001600160a01b03169163851c9e2b91869186916133399190600160401b90046001600160401b0316614880565b6040516001600160e01b031960e086901b168152600481019390935260248301919091526001600160401b03166044820152606401602060405180830381600087803b15801561338857600080fd5b505af115801561339c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133c09190614373565b8087556001546040519192506001600160a01b0316903480156108fc02916000818181858888f193505050501580156133fd573d6000803e3d6000fd5b5060408051338152602081018b90529081018290527fb38ba9b1c21d14e92c6b24ace95218359ca7727f16a3e622617817dd9f38305c9060600160405180910390a1505050505050505050565b6000806016848154811061346057613460614991565b9060005260206000209060020201905060006016848154811061348557613485614991565b6000918252602090912060018085015460029093029091019081015490925061ffff600160d01b92839004811692909104168110156134d057506001810154600160d01b900461ffff165b60015460405134916001600160a01b03169082156108fc029083906000818181858888f1935050505015801561350a573d6000803e3d6000fd5b506000878152601760205260408120546001600160a01b031690613540898961353487600161470f565b61ffff16600086612f20565b905061354b86613a74565b61355485613a74565b60008981526017602090815260409182902054600189015483516001600160a01b0390921682529181018490529182018b9052606082018a9052600160401b90046001600160401b031660808201527f2257b42f89acde8ceea38e863df4cb1ed40dc32b9469264383a7577eeda61ac09060a00160405180910390a198975050505050505050565b601080546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000806016838154811061364457613644614991565b60009182526020909120600160029092020101546001600160401b03438116600160401b9092041611159392505050565b61367e816139bf565b6040518181527f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df9060200160405180910390a150565b6136bf84848461293e565b6136cb84848484613b5a565b6120105760405162461bcd60e51b8152600401610f30906145ac565b60028101546000908190600160401b90046001600160401b031642111561372a57600283015461372790600160401b90046001600160401b031642614869565b90505b6001830154600284015461204b916001600160801b0380821692600160801b90920416906001600160401b031684613c6b565b6060816137815750506040805180820190915260018152600360fc1b602082015290565b8160005b81156137ab578061379581614920565b91506137a49050600a83614772565b9150613785565b6000816001600160401b038111156137c5576137c56149a7565b6040519080825280601f01601f1916602001820160405280156137ef576020820181803683370190505b5090505b84156122cf57613804600183614869565b9150613811600a8661493b565b61381c90603061472c565b60f81b81838151811061383157613831614991565b60200101906001600160f81b031916908160001a905350613853600a86614772565b94506137f3565b60006040518060800160405280604381526020016149f760439139805160209182012083518483015160408087015180519086012090516138ba950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60006138e2600e5490565b60405161190160f01b60208201526022810191909152604281018390526062016138ba565b6001600160a01b0383166139625761395d81600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b613985565b816001600160a01b0316836001600160a01b031614613985576139858382613cb9565b6001600160a01b03821661399c5761107881613d56565b826001600160a01b0316826001600160a01b031614611078576110788282613e05565b600090815260246020526040812080546001600160a01b0319168155600181019190915560020180546001600160801b0319169055565b600061271060235483613a09919061480b565b610e079190614772565b613a1d8282613e49565b6001600160a01b0382166000908152601860205260408120805491613a4183614920565b9091555050600090815260176020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6015546001820154439190601390600160c01b900461ffff16600e8110613a9d57613a9d614991565b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16613ac99190614772565b613ad3919061472c565b6001820180546fffffffffffffffff00000000000000001916600160401b6001600160401b0393909316929092029190911790819055600d600160c01b90910461ffff1610156125235760018181018054601890613b3d908490600160c01b900461ffff1661470f565b92506101000a81548161ffff021916908361ffff16021790555050565b60006001600160a01b0384163b15613c6357836001600160a01b031663150b7a02613b836126f6565b8786866040518563ffffffff1660e01b8152600401613ba59493929190614518565b602060405180830381600087803b158015613bbf57600080fd5b505af1925050508015613bef575060408051601f3d908101601f19168201909252613bec918101906142d8565b60015b613c49573d808015613c1d576040519150601f19603f3d011682016040523d82523d6000602084013e613c22565b606091505b508051613c415760405162461bcd60e51b8152600401610f30906145ac565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506122cf565b5060016122cf565b6000828210613c7b5750826122cf565b6000613c87868661482a565b9050600084613c968584614786565b613ca09190614744565b90506000613cae82896146ce565b93506122cf92505050565b60006001613cc6846125eb565b613cd09190614869565b6000838152600a6020526040902054909150808214613d23576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b54600090613d6890600190614869565b6000838152600c6020526040812054600b8054939450909284908110613d9057613d90614991565b9060005260206000200154905080600b8381548110613db157613db1614991565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b805480613de957613de961497b565b6001900381819060005260206000200160009055905550505050565b6000613e10836125eb565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b6001600160a01b038216613e9f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610f30565b6000818152600560205260409020546001600160a01b031615613f045760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610f30565b613f1060008383613907565b6001600160a01b0382166000908152600660205260408120805460019290613f3990849061472c565b909155505060008181526005602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054613fa3906148eb565b90600052602060002090601f016020900481019282613fc5576000855561400b565b82601f10613fde57805160ff191683800117855561400b565b8280016001018555821561400b579182015b8281111561400b578251825591602001919060010190613ff0565b5061401792915061401b565b5090565b5b80821115614017576000815560010161401c565b60006001600160401b038084111561404a5761404a6149a7565b604051601f8501601f19908116603f01168101908282118183101715614072576140726149a7565b8160405280935085815286868601111561408b57600080fd5b858560208301376000602087830101525050509392505050565b600082601f8301126140b657600080fd5b61204b83833560208501614030565b6000602082840312156140d757600080fd5b813561204b816149bd565b600080604083850312156140f557600080fd5b8235614100816149bd565b91506020830135614110816149bd565b809150509250929050565b60008060006060848603121561413057600080fd5b833561413b816149bd565b9250602084013561414b816149bd565b929592945050506040919091013590565b6000806000806080858703121561417257600080fd5b843561417d816149bd565b9350602085013561418d816149bd565b92506040850135915060608501356001600160401b038111156141af57600080fd5b6141bb878288016140a5565b91505092959194509250565b600080604083850312156141da57600080fd5b82356141e5816149bd565b91506020830135614110816149d2565b600080600080600060a0868803121561420d57600080fd5b8535614218816149bd565b945060208601356001600160401b0381111561423357600080fd5b61423f888289016140a5565b9450506040860135925060608601359150608086013560ff8116811461426457600080fd5b809150509295509295909350565b6000806040838503121561428557600080fd5b8235614290816149bd565b946020939093013593505050565b6000602082840312156142b057600080fd5b815161204b816149d2565b6000602082840312156142cd57600080fd5b813561204b816149e0565b6000602082840312156142ea57600080fd5b815161204b816149e0565b60006020828403121561430757600080fd5b815161204b816149bd565b60006020828403121561432457600080fd5b81356001600160401b0381111561433a57600080fd5b8201601f8101841361434b57600080fd5b6122cf84823560208401614030565b60006020828403121561436c57600080fd5b5035919050565b60006020828403121561438557600080fd5b5051919050565b6000806040838503121561439f57600080fd5b823591506020830135614110816149bd565b600080604083850312156143c457600080fd5b50508035926020909101359150565b6000806000606084860312156143e857600080fd5b505081359360208301359350604090920135919050565b600080600080600060a0868803121561441757600080fd5b853594506020860135935060408601359250606086013591506080860135614264816149bd565b600081518084526144568160208601602086016148a8565b601f01601f19169290920160200192915050565b6000825161447c8184602087016148a8565b9190910192915050565b600083516144988184602088016148a8565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b600083516144cf8184602088016148a8565b8351908301906144e38183602088016148a8565b01949350505050565b6001600160a01b038481168252831660208201526060604082018190526000906116c09083018461443e565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061454b9083018461443e565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561458d57835183529284019291840191600101614571565b50909695505050505050565b60208152600061204b602083018461443e565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604082015269726f206164647265737360b01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b600080821280156001600160ff1b03849003851316156146f0576146f061494f565b600160ff1b83900384128116156147095761470961494f565b50500190565b600061ffff8083168185168083038211156144e3576144e361494f565b6000821982111561473f5761473f61494f565b500190565b60008261475357614753614965565b600160ff1b82146000198414161561476d5761476d61494f565b500590565b60008261478157614781614965565b500490565b60006001600160ff1b03818413828413808216868404861116156147ac576147ac61494f565b600160ff1b60008712828116878305891216156147cb576147cb61494f565b600087129250878205871284841616156147e7576147e761494f565b878505871281841616156147fd576147fd61494f565b505050929093029392505050565b60008160001904831182151516156148255761482561494f565b500290565b60008083128015600160ff1b8501841216156148485761484861494f565b6001600160ff1b03840183138116156148635761486361494f565b50500390565b60008282101561487b5761487b61494f565b500390565b60006001600160401b03838116908316818110156148a0576148a061494f565b039392505050565b60005b838110156148c35781810151838201526020016148ab565b838111156120105750506000910152565b6000816148e3576148e361494f565b506000190190565b600181811c908216806148ff57607f821691505b60208210811415611d0c57634e487b7160e01b600052602260045260246000fd5b60006000198214156149345761493461494f565b5060010190565b60008261494a5761494a614965565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461252357600080fd5b801515811461252357600080fd5b6001600160e01b03198116811461252357600080fdfe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529a264697066735822122070b45eda88a8feb483a94a2759c4a46b69cd8c0bbd18b3c970990c8b5985e22b64736f6c63430008070033

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

000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1

-----Decoded View---------------
Arg [0] : _proxyRegistryAddress (address): 0xa5409ec958C83C3f309868babACA7c86DCB077c1

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1


Deployed Bytecode Sourcemap

102109:2542:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50222:224;;;;;;;;;;-1:-1:-1;50222:224:0;;;;;:::i;:::-;;:::i;:::-;;;14040:14:1;;14033:22;14015:41;;14003:2;13988:18;50222:224:0;;;;;;;;100619:96;;;;;;;;;;-1:-1:-1;100619:96:0;;;;;:::i;:::-;;:::i;:::-;;99782:55;;;;;;;;;;;;99832:5;99782:55;;;;;14979:25:1;;;14967:2;14952:18;99782:55:0;14833:177:1;58970:25:0;;;;;;;;;;-1:-1:-1;58970:25:0;;;;-1:-1:-1;;;;;58970:25:0;;;;;;-1:-1:-1;;;;;9666:32:1;;;9648:51;;9636:2;9621:18;58970:25:0;9502:203:1;99912:32:0;;;;;;;;;;;;;;;;38114:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;39673:221::-;;;;;;;;;;-1:-1:-1;39673:221:0;;;;;:::i;:::-;;:::i;39196:411::-;;;;;;;;;;-1:-1:-1;39196:411:0;;;;;:::i;:::-;;:::i;58938:25::-;;;;;;;;;;-1:-1:-1;58938:25:0;;;;-1:-1:-1;;;;;58938:25:0;;;11070:1151;;;;;;:::i;:::-;;:::i;518:43::-;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;518:43:0;;;;;50862:113;;;;;;;;;;-1:-1:-1;50950:10:0;:17;50862:113;;71357:31;;;;;;;;;;;;;;;;100849:96;;;;;;;;;;-1:-1:-1;100849:96:0;;;;;:::i;:::-;;:::i;1527:101::-;;;;;;;;;;-1:-1:-1;1605:15:0;;1527:101;;100032:35;;;;;;;;;;-1:-1:-1;100032:35:0;;;;;;;;40563:339;;;;;;;;;;-1:-1:-1;40563:339:0;;;;;:::i;:::-;;:::i;59742:132::-;;;;;;;;;;-1:-1:-1;59742:132:0;;;;;:::i;:::-;;:::i;95399:1062::-;;;;;;;;;;-1:-1:-1;95399:1062:0;;;;;:::i;:::-;;:::i;60312:132::-;;;;;;;;;;-1:-1:-1;60312:132:0;;;;;:::i;:::-;;:::i;12647:107::-;;;;;;;;;;-1:-1:-1;12647:107:0;;;;;:::i;:::-;-1:-1:-1;;;;;12734:12:0;12700:13;12734:12;;;:6;:12;;;;;;;12647:107;100421:92;;;;;;;;;;;;;:::i;50530:256::-;;;;;;;;;;-1:-1:-1;50530:256:0;;;;;:::i;:::-;;:::i;102939:107::-;;;;;;;;;;-1:-1:-1;102939:107:0;;;;;:::i;:::-;;:::i;1636:161::-;;;;;;;;;;-1:-1:-1;1750:9:0;1636:161;;103475:188;;;;;;;;;;;;;:::i;40973:185::-;;;;;;;;;;-1:-1:-1;40973:185:0;;;;;:::i;:::-;;:::i;96473:655::-;;;;;;:::i;:::-;;:::i;77579:384::-;;;;;;;;;;-1:-1:-1;77579:384:0;;;;;:::i;:::-;;:::i;85159:36::-;;;;;;;;;;-1:-1:-1;85159:36:0;;;;;:::i;:::-;;:::i;60023:140::-;;;;;;;;;;-1:-1:-1;60023:140:0;;;;;:::i;:::-;;:::i;51052:233::-;;;;;;;;;;-1:-1:-1;51052:233:0;;;;;:::i;:::-;;:::i;74493:84::-;;;;;;;;;;-1:-1:-1;74493:84:0;;;;;:::i;:::-;;:::i;68648:142::-;;;;;;;;;;-1:-1:-1;68648:142:0;;;;;:::i;:::-;;:::i;59093:26::-;;;;;;;;;;-1:-1:-1;59093:26:0;;;;-1:-1:-1;;;59093:26:0;;;;;;100201:35;;;;;;;;;;;;;;;;66450:215;;;;;;;;;;-1:-1:-1;66450:215:0;;;;;:::i;:::-;;:::i;100953:524::-;;;;;;:::i;:::-;;:::i;83232:381::-;;;;;;:::i;:::-;;:::i;79292:1127::-;;;;;;:::i;:::-;;:::i;66674:210::-;;;;;;;;;;-1:-1:-1;66674:210:0;;;;;:::i;:::-;;:::i;17813:94::-;;;;;;;;;;;;;:::i;86034:146::-;;;;;;;;;;-1:-1:-1;86034:146:0;;;;;:::i;:::-;;:::i;98588:545::-;;;;;;;;;;-1:-1:-1;98588:545:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;11266:32:1;;;11248:51;;11330:2;11315:18;;11308:34;;;;11358:18;;;11351:34;;;;11416:2;11401:18;;11394:34;11459:3;11444:19;;11437:35;11235:3;11220:19;98588:545:0;10989:489:1;64476:35:0;;;;;;;;;;;;;;;;75226:178;;;;;;;;;;-1:-1:-1;75226:178:0;;;;;:::i;:::-;;:::i;85842:29::-;;;;;;;;;;;;;;;;60971:83;;;;;;;;;;;;;:::i;67352:905::-;;;;;;;;;;-1:-1:-1;67352:905:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;98213:260::-;;;;;;;;;;-1:-1:-1;98213:260:0;;;;;:::i;:::-;;:::i;85120:28::-;;;;;;;;;;;;;;;;17162:87;;;;;;;;;;-1:-1:-1;17235:6:0;;-1:-1:-1;;;;;17235:6:0;17162:87;;74191:84;;;;;;;;;;-1:-1:-1;74191:84:0;;;;;:::i;:::-;;:::i;103054:122::-;;;;;;;;;;-1:-1:-1;103054:122:0;;;;;:::i;:::-;;:::i;38283:104::-;;;;;;;;;;;;;:::i;97661:293::-;;;;;;;;;;-1:-1:-1;97661:293:0;;;;;:::i;:::-;;:::i;63979:410::-;;;;;;;;;;-1:-1:-1;63979:410:0;;;;;:::i;:::-;;:::i;:::-;;;25533:10:1;25521:23;;;25503:42;;25491:2;25476:18;63979:410:0;25359:192:1;39966:295:0;;;;;;;;;;-1:-1:-1;39966:295:0;;;;;:::i;:::-;;:::i;70302:921::-;;;;;;;;;;-1:-1:-1;70302:921:0;;;;;:::i;:::-;;:::i;59002:25::-;;;;;;;;;;-1:-1:-1;59002:25:0;;;;-1:-1:-1;;;;;59002:25:0;;;41229:328;;;;;;;;;;-1:-1:-1;41229:328:0;;;;;:::i;:::-;;:::i;99262:259::-;;;;;;;;;;-1:-1:-1;99262:259:0;;;;;:::i;:::-;;:::i;103184:175::-;;;;;;;;;;-1:-1:-1;103184:175:0;;;;;:::i;:::-;;:::i;74790:223::-;;;;;;;;;;-1:-1:-1;74790:223:0;;;;;:::i;:::-;;:::i;102838:93::-;;;;;;;;;;;;;:::i;100137:55::-;;;;;;;;;;;;;;;;100285:89;;;;;;;;;;;;;:::i;71793:480::-;;;;;;;;;;-1:-1:-1;71793:480:0;;;;;:::i;:::-;;:::i;99724:51::-;;;;;;;;;;;;99771:4;99724:51;;103367:100;;;;;;;;;;;;;:::i;57318:445::-;;;;;;;;;;-1:-1:-1;57318:445:0;;;;;:::i;:::-;;:::i;97140:244::-;;;;;;;;;;;;;:::i;103804:844::-;;;;;;;;;;-1:-1:-1;103804:844:0;;;;;:::i;:::-;;:::i;:::-;;;;14457:14:1;;14450:22;14432:41;;14504:2;14489:18;;14482:34;;;;14532:18;;;14525:34;;;;14590:2;14575:18;;14568:34;;;;14633:3;14618:19;;14611:35;;;;14677:3;14662:19;;14655:35;14721:3;14706:19;;14699:35;14765:3;14750:19;;14743:35;14809:3;14794:19;;14787:35;14419:3;14404:19;103804:844:0;14067:761:1;99951:31:0;;;;;;;;;;;;;;;;18062:192;;;;;;;;;;-1:-1:-1;18062:192:0;;;;;:::i;:::-;;:::i;101736:364::-;;;;;;;;;;-1:-1:-1;101736:364:0;;;;;:::i;:::-;;:::i;71397:31::-;;;;;;;;;;;;;;;;71548:40;;;;;;;;;;-1:-1:-1;71548:40:0;;;;-1:-1:-1;;;;;71548:40:0;;;50222:224;50324:4;-1:-1:-1;;;;;;50348:50:0;;-1:-1:-1;;;50348:50:0;;:90;;;50402:36;50426:11;50402:23;:36::i;:::-;50341:97;50222:224;-1:-1:-1;;50222:224:0:o;100619:96::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;100687:14:::1;:20:::0;100619:96::o;38114:100::-;38168:13;38201:5;38194:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38114:100;:::o;39673:221::-;39749:7;43156:16;;;:7;:16;;;;;;-1:-1:-1;;;;;43156:16:0;39769:73;;;;-1:-1:-1;;;39769:73:0;;21862:2:1;39769:73:0;;;21844:21:1;21901:2;21881:18;;;21874:30;21940:34;21920:18;;;21913:62;-1:-1:-1;;;21991:18:1;;;21984:42;22043:19;;39769:73:0;;;;;;;;;-1:-1:-1;39862:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;39862:24:0;;39673:221::o;39196:411::-;39277:13;39293:23;39308:7;39293:14;:23::i;:::-;39277:39;;39341:5;-1:-1:-1;;;;;39335:11:0;:2;-1:-1:-1;;;;;39335:11:0;;;39327:57;;;;-1:-1:-1;;;39327:57:0;;23448:2:1;39327:57:0;;;23430:21:1;23487:2;23467:18;;;23460:30;23526:34;23506:18;;;23499:62;-1:-1:-1;;;23577:18:1;;;23570:31;23618:19;;39327:57:0;23246:397:1;39327:57:0;39435:5;-1:-1:-1;;;;;39419:21:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;39419:21:0;;:62;;;;39444:37;39461:5;39468:12;:10;:12::i;39444:37::-;39397:168;;;;-1:-1:-1;;;39397:168:0;;20255:2:1;39397:168:0;;;20237:21:1;20294:2;20274:18;;;20267:30;20333:34;20313:18;;;20306:62;20404:26;20384:18;;;20377:54;20448:19;;39397:168:0;20053:420:1;39397:168:0;39578:21;39587:2;39591:7;39578:8;:21::i;:::-;39266:341;39196:411;;:::o;11070:1151::-;11328:152;;;11271:12;11328:152;;;;;-1:-1:-1;;;;;11366:19:0;;11296:29;11366:19;;;:6;:19;;;;;;;;;11328:152;;;;;;;;;;;11515:45;11373:11;11328:152;11543:4;11549;11555;11515:6;:45::i;:::-;11493:128;;;;-1:-1:-1;;;11493:128:0;;23046:2:1;11493:128:0;;;23028:21:1;23085:2;23065:18;;;23058:30;23124:34;23104:18;;;23097:62;-1:-1:-1;;;23175:18:1;;;23168:31;23216:19;;11493:128:0;22844:397:1;11493:128:0;-1:-1:-1;;;;;11710:19:0;;;;;;:6;:19;;;;;;:26;;11734:1;11710:23;:26::i;:::-;-1:-1:-1;;;;;11688:19:0;;;;;;:6;:19;;;;;;;:48;;;;11754:126;;;;;11695:11;;11826:10;;11852:17;;11754:126;:::i;:::-;;;;;;;;11991:12;12005:23;12040:4;-1:-1:-1;;;;;12032:18:0;12082:17;12101:11;12065:48;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;12065:48:0;;;;;;;;;;12032:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11990:134;;;;12143:7;12135:48;;;;-1:-1:-1;;;12135:48:0;;17963:2:1;12135:48:0;;;17945:21:1;18002:2;17982:18;;;17975:30;18041;18021:18;;;18014:58;18089:18;;12135:48:0;17761:352:1;12135:48:0;12203:10;11070:1151;-1:-1:-1;;;;;;;;11070:1151:0:o;100849:96::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;100917:14:::1;:20:::0;100849:96::o;40563:339::-;40758:41;40777:12;:10;:12::i;:::-;40791:7;40758:18;:41::i;:::-;40750:103;;;;-1:-1:-1;;;40750:103:0;;;;;;;:::i;:::-;40866:28;40876:4;40882:2;40886:7;40866:9;:28::i;59742:132::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;-1:-1:-1;;;;;59811:21:0;::::1;59803:30;;;::::0;::::1;;59846:10;:20:::0;;-1:-1:-1;;;;;;59846:20:0::1;-1:-1:-1::0;;;;;59846:20:0;;;::::1;::::0;;;::::1;::::0;;59742:132::o;95399:1062::-;60640:6;;-1:-1:-1;;;60640:6:0;;;;60639:7;60631:16;;;;;;95849:14:::1;-1:-1:-1::0;;;;;95833:32:0::1;95815:14;:50;95807:59;;;::::0;::::1;;95921:12;-1:-1:-1::0;;;;;95905:30:0::1;95889:12;:46;95881:55;;;::::0;::::1;;95987:9;-1:-1:-1::0;;;;;95972:26:0::1;95959:9;:39;95951:48;;;::::0;::::1;;96040:12;96022:14;:30;;96014:39;;;::::0;::::1;;96090:28;::::0;;;:18:::1;:28;::::0;;;;;-1:-1:-1;;;;;96090:28:0::1;96076:10;:42;96068:51;;;::::0;::::1;;96136:22;96161:217;;;;;;;;96195:7;-1:-1:-1::0;;;;;96161:217:0::1;;;;;96230:14;-1:-1:-1::0;;;;;96161:217:0::1;;;;;96272:12;-1:-1:-1::0;;;;;96161:217:0::1;;;;;96311:9;-1:-1:-1::0;;;;;96161:217:0::1;;;;;96347:15;-1:-1:-1::0;;;;;96161:217:0::1;;;::::0;96136:242:::1;;96393:56;96405:7;96414:8;96424:7;96433:15;96393:11;:56::i;:::-;95656:805;95399:1062:::0;;;;;:::o;60312:132::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;-1:-1:-1;;;;;60381:21:0;::::1;60373:30;;;::::0;::::1;;60416:10;:20:::0;;-1:-1:-1;;;;;;60416:20:0::1;-1:-1:-1::0;;;;;60416:20:0;;;::::1;::::0;;;::::1;::::0;;60312:132::o;100421:92::-;59470:10;;-1:-1:-1;;;;;59470:10:0;59456;:24;;:65;;-1:-1:-1;59511:10:0;;-1:-1:-1;;;;;59511:10:0;59497;:24;59456:65;:106;;;-1:-1:-1;59552:10:0;;-1:-1:-1;;;;;59552:10:0;59538;:24;59456:106;59434:139;;;;;;100481:16:::1;:24:::0;;-1:-1:-1;;100481:24:0::1;::::0;;100421:92::o;50530:256::-;50627:7;50663:23;50680:5;50663:16;:23::i;:::-;50655:5;:31;50647:87;;;;-1:-1:-1;;;50647:87:0;;16725:2:1;50647:87:0;;;16707:21:1;16764:2;16744:18;;;16737:30;16803:34;16783:18;;;16776:62;-1:-1:-1;;;16854:18:1;;;16847:41;16905:19;;50647:87:0;16523:407:1;50647:87:0;-1:-1:-1;;;;;;50752:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;50530:256::o;102939:107::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;103017:21;;::::1;::::0;:7:::1;::::0;:21:::1;::::0;::::1;::::0;::::1;:::i;:::-;;102939:107:::0;:::o;103475:188::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;60787:6:::1;::::0;-1:-1:-1;;;60787:6:0;::::1;;;60779:15;;;::::0;::::1;;103556:12:::2;::::0;-1:-1:-1;;;;;103556:12:0::2;103540:44;;;::::0;::::2;;103640:15;:13;:15::i;:::-;103475:188::o:0;40973:185::-;41111:39;41128:4;41134:2;41138:7;41111:39;;;;;;;;;;;;:16;:39::i;96473:655::-;60640:6;;-1:-1:-1;;;60640:6:0;;;;60639:7;60631:16;;;;;;96709:14:::1;96726:26:::0;;;:16:::1;:26;::::0;;;;:33;-1:-1:-1;;;;;96726:33:0::1;::::0;96790:25:::1;96743:8:::0;96805:9:::1;96790:4;:25::i;:::-;96774:41:::0;-1:-1:-1;;;;;;96879:23:0;::::1;96897:4;96879:23;96875:186;;;97006:5;96966:18;97001:1;96985:13;;:17;;;;:::i;:::-;96966:37;;;;;;;:::i;:::-;;:45:::0;97030:13:::1;:15:::0;;;:13:::1;:15;::::0;::::1;:::i;:::-;;;;;;96875:186;97077:39;97087:6;97095:10;97107:8;97077:9;:39::i;77579:384::-:0;77690:4;77733:1;77720:10;:14;77712:23;;;;;;77767:1;77754:10;:14;77746:23;;;;;;77780:22;77805:6;77812:10;77805:18;;;;;;;;:::i;:::-;;;;;;;;;;;77780:43;;77834:22;77859:6;77866:10;77859:18;;;;;;;;:::i;:::-;;;;;;;;;;;77834:43;;77895:60;77914:7;77923:10;77935:7;77944:10;77895:18;:60::i;:::-;77888:67;77579:384;-1:-1:-1;;;;;77579:384:0:o;85159:36::-;;;;;;;;;;;;;;;-1:-1:-1;85159:36:0;:::o;60023:140::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;-1:-1:-1;;;;;60100:21:0;::::1;60092:30;;;::::0;::::1;;60135:10;:20:::0;;-1:-1:-1;;;;;;60135:20:0::1;-1:-1:-1::0;;;;;60135:20:0;;;::::1;::::0;;;::::1;::::0;;60023:140::o;51052:233::-;51127:7;51163:30;50950:10;:17;;50862:113;51163:30;51155:5;:38;51147:95;;;;-1:-1:-1;;;51147:95:0;;24268:2:1;51147:95:0;;;24250:21:1;24307:2;24287:18;;;24280:30;24346:34;24326:18;;;24319:62;-1:-1:-1;;;24397:18:1;;;24390:42;24449:19;;51147:95:0;24066:408:1;51147:95:0;51260:10;51271:5;51260:17;;;;;;;;:::i;:::-;;;;;;;;;51253:24;;51052:233;;;:::o;74493:84::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;74555:8:::1;:14:::0;74493:84::o;68648:142::-;59470:10;;-1:-1:-1;;;;;59470:10:0;59456;:24;;:65;;-1:-1:-1;59511:10:0;;-1:-1:-1;;;;;59511:10:0;59497;:24;59456:65;:106;;;-1:-1:-1;59552:10:0;;-1:-1:-1;;;;;59552:10:0;59538;:24;59456:106;59434:139;;;;;;68736:9:::1;:12:::0;::::1;;68729:19:::0;::::1;68721:28;;;::::0;::::1;;68760:15;:22:::0;68648:142::o;66450:215::-;66551:13;66590:28;;;:18;:28;;;;;;-1:-1:-1;;;;;66590:28:0;66637:19;66629:28;;;;;;66450:215;;;:::o;100953:524::-;101028:16;;;;101027:17;101018:27;;;;;;101078:14;;101065:9;:27;;101056:37;;;;;;101132:14;;101113:16;;:33;101104:43;;;;;;99832:5;101167:16;;:42;101158:52;;;;;;101312:10;;101296:48;;-1:-1:-1;;;;;101312:10:0;;;;101334:9;101296:48;;;;;101312:10;101296:48;101312:10;101296:48;101334:9;101312:10;101296:48;;;;;;;;;;;;;;;;;;;;-1:-1:-1;101398:16:0;:18;;101379:6;;101357:19;101398:18;;;:::i;:::-;;;;;;101429:38;101443:1;101446;101449;101452;101455:11;101429:13;:38::i;83232:381::-;60640:6;;-1:-1:-1;;;60640:6:0;;;;60639:7;60631:16;;;;;;83433:8:::1;;83420:9;:21;;83412:30;;;::::0;::::1;;83524:26;83530:10;83542:7;83524:5;:26::i;:::-;83516:35;;;::::0;::::1;;83564:41;83575:7;83584:9;83595;83564:10;:41::i;79292:1127::-:0;60640:6;;-1:-1:-1;;;60640:6:0;;;;60639:7;60631:16;;;;;;79478:8:::1;;79465:9;:21;;79457:30;;;::::0;::::1;;79562:29;79568:10;79580;79562:5;:29::i;:::-;79554:38;;;::::0;::::1;;79611:29;79617:10;79629;79611:5;:29::i;:::-;79603:38;;;::::0;::::1;;79703:22;79728:6;79735:10;79728:18;;;;;;;;:::i;:::-;;;;;;;;;;;79703:43;;79851:24;79867:7;73039:22:::0;;;-1:-1:-1;;;;;73072:12:0;73039:46;;-1:-1:-1;;;73039:22:0;;;;:46;;;72709:384;79851:24:::1;79843:33;;;::::0;::::1;;79939:22;79964:6;79971:10;79964:18;;;;;;;;:::i;:::-;;;;;;;;;;;79939:43;;80087:24;80103:7;73039:22:::0;;;-1:-1:-1;;;;;73072:12:0;73039:46;;-1:-1:-1;;;73039:22:0;;;;:46;;;72709:384;80087:24:::1;80079:33;;;::::0;::::1;;80191:123;80224:7;80246:10;80271:7;80293:10;80191:18;:123::i;:::-;80183:132;;;::::0;::::1;;80377:34;80388:10;80400;80377;:34::i;:::-;;79414:1005;;79292:1127:::0;;:::o;66674:210::-;66738:7;-1:-1:-1;;;;;66766:19:0;;66758:74;;;;-1:-1:-1;;;66758:74:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;;66850:26:0;;;;;:19;:26;;;;;;;66674:210::o;17813:94::-;17393:12;:10;:12::i;:::-;-1:-1:-1;;;;;17382:23:0;:7;17235:6;;-1:-1:-1;;;;;17235:6:0;;17162:87;17382:7;-1:-1:-1;;;;;17382:23:0;;17374:68;;;;-1:-1:-1;;;17374:68:0;;;;;;;:::i;:::-;17878:21:::1;17896:1;17878:9;:21::i;86034:146::-:0;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;86127:5:::1;86114:9;:18;;86106:27;;;::::0;::::1;;86148:8;:20:::0;86034:146::o;98588:545::-;98691:14;98867:26;;;:16;:26;;;;;91194:18;;;;98691:14;;;;;;;;-1:-1:-1;;;91194:18:0;;-1:-1:-1;;;;;91194:18:0;98904:30;;;;;;98967:14;;;98996:21;;;99066:16;;;;;-1:-1:-1;;;;;98967:14:0;;;;-1:-1:-1;;;;;98996:21:0;;;;-1:-1:-1;;;;99032:19:0;;;;;;;-1:-1:-1;;;;;;99066:16:0;;;;-1:-1:-1;;;;99097:17:0;;;;;-1:-1:-1;98588:545:0;-1:-1:-1;;98588:545:0:o;75226:178::-;75314:4;75353:1;75344:6;:10;75336:19;;;;;;75373:23;75389:6;75373:15;:23::i;60971:83::-;59470:10;;-1:-1:-1;;;;;59470:10:0;59456;:24;;:65;;-1:-1:-1;59511:10:0;;-1:-1:-1;;;;;59511:10:0;59497;:24;59456:65;:106;;;-1:-1:-1;59552:10:0;;-1:-1:-1;;;;;59552:10:0;59538;:24;59456:106;59434:139;;;;;;60640:6:::1;::::0;-1:-1:-1;;;60640:6:0;::::1;;;60639:7;60631:16;;;::::0;::::1;;61033:6:::2;:13:::0;;-1:-1:-1;;;;61033:13:0::2;-1:-1:-1::0;;;61033:13:0::2;::::0;;60971:83::o;67352:905::-;67413:28;67454:18;67475:17;67485:6;67475:9;:17::i;:::-;67454:38;-1:-1:-1;67509:15:0;67505:745;;-1:-1:-1;;67586:16:0;;;67600:1;67586:16;;;;;;;;;67579:23;-1:-1:-1;67352:905:0:o;67505:745::-;67635:23;67675:10;-1:-1:-1;;;;;67661:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;67661:25:0;;67635:51;;67701:19;67723:13;50950:10;:17;;50862:113;67723:13;67701:35;-1:-1:-1;67751:19:0;67984:1;67968:243;67999:11;67987:8;:23;67968:243;;68047:28;;;;:18;:28;;;;;;-1:-1:-1;;;;;68047:38:0;;;:28;;:38;68043:153;;;68132:8;68110:6;68117:11;68110:19;;;;;;;;:::i;:::-;;;;;;;;;;:30;68163:13;;;;:::i;:::-;;;;68043:153;68012:10;;;;:::i;:::-;;;;67968:243;;;-1:-1:-1;68232:6:0;;67352:905;-1:-1:-1;;;;;67352:905:0:o;67505:745::-;67443:814;67352:905;;;:::o;98213:260::-;60787:6;;-1:-1:-1;;;60787:6:0;;;;60779:15;;;;;;17393:12:::1;:10;:12::i;:::-;-1:-1:-1::0;;;;;17382:23:0::1;:7;17235:6:::0;;-1:-1:-1;;;;;17235:6:0;;17162:87;17382:7:::1;-1:-1:-1::0;;;;;17382:23:0::1;;17374:68;;;;-1:-1:-1::0;;;17374:68:0::1;;;;;;;:::i;:::-;98337:23:::2;98363:26:::0;;;:16:::2;:26;::::0;;;;91194:18;;;;-1:-1:-1;;;91194:18:0;;-1:-1:-1;;;;;91194:18:0;98400:30:::2;;;::::0;::::2;;98441:24;98456:8;98441:14;:24::i;74191:84::-:0;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;74253:8:::1;:14:::0;74191:84::o;103054:122::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;103135;;::::1;::::0;:15:::1;::::0;:33:::1;::::0;::::1;::::0;::::1;:::i;38283:104::-:0;38339:13;38372:7;38365:14;;;;;:::i;97661:293::-;97736:23;97762:26;;;:16;:26;;;;;91194:18;;;;-1:-1:-1;;;91194:18:0;;-1:-1:-1;;;;;91194:18:0;97799:30;;;;;;97857:14;;-1:-1:-1;;;;;97857:14:0;97890:10;:20;;97882:29;;;;;;97922:24;97937:8;97922:14;:24::i;63979:410::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;39966:295::-;40081:12;:10;:12::i;:::-;-1:-1:-1;;;;;40069:24:0;:8;-1:-1:-1;;;;;40069:24:0;;;40061:62;;;;-1:-1:-1;;;40061:62:0;;19082:2:1;40061:62:0;;;19064:21:1;19121:2;19101:18;;;19094:30;19160:27;19140:18;;;19133:55;19205:18;;40061:62:0;18880:349:1;40061:62:0;40181:8;40136:18;:32;40155:12;:10;:12::i;:::-;-1:-1:-1;;;;;40136:32:0;;;;;;;;;;;;;;;;;-1:-1:-1;40136:32:0;;;:42;;;;;;;;;;;;:53;;-1:-1:-1;;40136:53:0;;;;;;;;;;;40220:12;:10;:12::i;:::-;-1:-1:-1;;;;;40205:48:0;;40244:8;40205:48;;;;14040:14:1;14033:22;14015:41;;14003:2;13988:18;;13875:187;40205:48:0;;;;;;;;39966:295;;:::o;70302:921::-;60640:6;;-1:-1:-1;;;60640:6:0;;;;60639:7;60631:16;;;;;;-1:-1:-1;;;;;70512:17:0;::::1;70504:26;;;::::0;::::1;;-1:-1:-1::0;;;;;70772:20:0;::::1;70787:4;70772:20;;70764:29;;;::::0;::::1;;71060:27;71066:10;71078:8;71060:5;:27::i;:::-;71052:36;;;::::0;::::1;;71179;71189:10;71201:3;71206:8;71179:9;:36::i;41229:328::-:0;41404:41;41423:12;:10;:12::i;:::-;41437:7;41404:18;:41::i;:::-;41396:103;;;;-1:-1:-1;;;41396:103:0;;;;;;;:::i;:::-;41510:39;41524:4;41530:2;41534:7;41543:5;41510:13;:39::i;:::-;41229:328;;;;:::o;99262:259::-;99355:7;99406:26;;;:16;:26;;;;;91194:18;;;;-1:-1:-1;;;91194:18:0;;-1:-1:-1;;;;;91194:18:0;99443:30;;;;;;99491:22;99505:7;99491:13;:22::i;:::-;99484:29;99262:259;-1:-1:-1;;;99262:259:0:o;103184:175::-;103250:13;103307:14;:12;:14::i;:::-;103323:26;103340:8;103323:16;:26::i;:::-;103290:60;;;;;;;;;:::i;:::-;;;;;;;;;;;;;103276:75;;103184:175;;;:::o;74790:223::-;74878:4;74917:1;74908:6;:10;74900:19;;;;;;74930;74952:6;74959;74952:14;;;;;;;;:::i;:::-;;;;;;;;;;;74930:36;;74984:21;75000:4;73039:22;;;-1:-1:-1;;;;;73072:12:0;73039:46;;-1:-1:-1;;;73039:22:0;;;;:46;;;72709:384;102838:93;102883:13;102916:7;102909:14;;;;;:::i;100285:89::-;59470:10;;-1:-1:-1;;;;;59470:10:0;59456;:24;;:65;;-1:-1:-1;59511:10:0;;-1:-1:-1;;;;;59511:10:0;59497;:24;59456:65;:106;;;-1:-1:-1;59552:10:0;;-1:-1:-1;;;;;59552:10:0;59538;:24;59456:106;59434:139;;;;;;100343:16:::1;:23:::0;;-1:-1:-1;;100343:23:0::1;100362:4;100343:23;::::0;;100285:89::o;71793:480::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;71870:38:::1;71932:8;71870:71;;72144:17;-1:-1:-1::0;;;;;72144:32:0::1;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72136:43;;;::::0;::::1;;72233:12;:32:::0;;-1:-1:-1;;;;;;72233:32:0::1;-1:-1:-1::0;;;;;72233:32:0;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;71793:480:0:o;103367:100::-;103411:13;103444:15;103437:22;;;;;:::i;57318:445::-;57572:20;;57616:28;;-1:-1:-1;;;57616:28:0;;-1:-1:-1;;;;;9666:32:1;;;57616:28:0;;;9648:51:1;57443:4:0;;57572:20;;;57608:49;;;;57572:20;;57616:21;;9621:18:1;;57616:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;57608:49:0;;57604:93;;;57681:4;57674:11;;;;;57604:93;-1:-1:-1;;;;;40453:25:0;;;40429:4;40453:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;57716:39;57709:46;57318:445;-1:-1:-1;;;;57318:445:0:o;97140:244::-;97195:7;;;97249:95;97273:1;97269;:5;97249:95;;;97307:18;97326:1;97307:21;;;;;;;:::i;:::-;;;97300:28;;;;:::i;:::-;;-1:-1:-1;97276:3:0;;;;:::i;:::-;;;;97249:95;;;-1:-1:-1;97365:7:0;97371:1;97365:3;:7;:::i;:::-;97358:14;;;97140:244;:::o;103804:844::-;103896:12;103919:21;103951:20;103982:17;104010;104038;104066:18;104095:24;104130:13;104162:19;104184:6;104191:3;104184:11;;;;;;;;:::i;:::-;;;;;;;;;;;104162:33;;104242:12;104217:4;:21;;;;;;;;;;-1:-1:-1;;;;;104217:21:0;-1:-1:-1;;;;;104217:37:0;;;104206:49;;104290:4;:18;;;;;;;;;;;;104282:27;;104266:43;;104343:4;:21;;;;;;;;;;-1:-1:-1;;;;;104343:21:0;-1:-1:-1;;;;;104335:30:0;104320:45;;104396:4;:14;;;;;;;;;;-1:-1:-1;;;;;104396:14:0;-1:-1:-1;;;;;104388:23:0;104376:35;;104442:4;:14;;;;;;;;;;;;104434:23;;104422:35;;104488:4;:14;;;;;;;;;;;;104480:23;;104468:35;;104535:4;:15;;;;;;;;;;;;104527:24;;104514:37;;104589:4;:21;;;;;;;;;;-1:-1:-1;;;;;104589:21:0;-1:-1:-1;;;;;104581:30:0;104562:49;;104630:4;:10;;;104622:18;;104151:497;103804:844;;;;;;;;;;;:::o;18062:192::-;17393:12;:10;:12::i;:::-;-1:-1:-1;;;;;17382:23:0;:7;17235:6;;-1:-1:-1;;;;;17235:6:0;;17162:87;17382:7;-1:-1:-1;;;;;17382:23:0;;17374:68;;;;-1:-1:-1;;;17374:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;18151:22:0;::::1;18143:73;;;::::0;-1:-1:-1;;;18143:73:0;;17556:2:1;18143:73:0::1;::::0;::::1;17538:21:1::0;17595:2;17575:18;;;17568:30;17634:34;17614:18;;;17607:62;-1:-1:-1;;;17685:18:1;;;17678:36;17731:19;;18143:73:0::1;17354:402:1::0;18143:73:0::1;18227:19;18237:8;18227:9;:19::i;:::-;18062:192:::0;:::o;101736:364::-;59362:10;;-1:-1:-1;;;;;59362:10:0;59348;:24;59340:33;;;;;;101843:6;-1:-1:-1;;;;;101866:25:0;::::1;101862:83;;-1:-1:-1::0;101923:10:0::1;::::0;-1:-1:-1;;;;;101923:10:0::1;101862:83;99771:4;101965:17;;:40;101957:49;;;::::0;::::1;;102019:17;:19:::0;;;:17:::1;:19;::::0;::::1;:::i;:::-;;;;;;102049:43;102063:1;102066::::0;102069::::1;102072:6;102080:11;102049:13;:43::i;2546:650::-:0;2617:22;2661:10;2683:4;2661:27;2657:508;;;2705:18;2726:8;;2705:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;2765:8:0;2976:17;2970:24;-1:-1:-1;;;;;2944:134:0;;-1:-1:-1;2657:508:0;;-1:-1:-1;2657:508:0;;-1:-1:-1;3142:10:0;2657:508;2546:650;:::o;37538:208::-;37610:7;-1:-1:-1;;;;;37638:19:0;;37630:74;;;;-1:-1:-1;;;37630:74:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;;37722:16:0;;;;;:9;:16;;;;;;;37538:208::o;37169:305::-;37271:4;-1:-1:-1;;;;;;37308:40:0;;-1:-1:-1;;;37308:40:0;;:105;;-1:-1:-1;;;;;;;37365:48:0;;-1:-1:-1;;;37365:48:0;37308:105;:158;;;-1:-1:-1;;;;;;;;;;29257:40:0;;;37430:36;29148:157;37808:239;37880:7;37916:16;;;:7;:16;;;;;;-1:-1:-1;;;;;37916:16:0;37951:19;37943:73;;;;-1:-1:-1;;;37943:73:0;;21091:2:1;37943:73:0;;;21073:21:1;21130:2;21110:18;;;21103:30;21169:34;21149:18;;;21142:62;-1:-1:-1;;;21220:18:1;;;21213:39;21269:19;;37943:73:0;20889:405:1;57907:161:0;57997:14;58036:24;:22;:24::i;:::-;58029:31;;57907:161;:::o;47049:174::-;47124:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;47124:29:0;-1:-1:-1;;;;;47124:29:0;;;;;;;;:24;;47178:23;47124:24;47178:14;:23::i;:::-;-1:-1:-1;;;;;47169:46:0;;;;;;;;;;;47049:174;;:::o;12762:486::-;12940:4;-1:-1:-1;;;;;12965:20:0;;12957:70;;;;-1:-1:-1;;;12957:70:0;;19849:2:1;12957:70:0;;;19831:21:1;19888:2;19868:18;;;19861:30;19927:34;19907:18;;;19900:62;-1:-1:-1;;;19978:18:1;;;19971:35;20023:19;;12957:70:0;19647:401:1;12957:70:0;13081:159;13109:47;13128:27;13148:6;13128:19;:27::i;:::-;13109:18;:47::i;:::-;13081:159;;;;;;;;;;;;15664:25:1;;;;15737:4;15725:17;;15705:18;;;15698:45;15759:18;;;15752:34;;;15802:18;;;15795:34;;;15636:19;;13081:159:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;13058:182:0;:6;-1:-1:-1;;;;;13058:182:0;;13038:202;;12762:486;;;;;;;:::o;5993:98::-;6051:7;6078:5;6082:1;6078;:5;:::i;43361:348::-;43454:4;43156:16;;;:7;:16;;;;;;-1:-1:-1;;;;;43156:16:0;43471:73;;;;-1:-1:-1;;;43471:73:0;;19436:2:1;43471:73:0;;;19418:21:1;19475:2;19455:18;;;19448:30;19514:34;19494:18;;;19487:62;-1:-1:-1;;;19565:18:1;;;19558:42;19617:19;;43471:73:0;19234:408:1;43471:73:0;43555:13;43571:23;43586:7;43571:14;:23::i;:::-;43555:39;;43624:5;-1:-1:-1;;;;;43613:16:0;:7;-1:-1:-1;;;;;43613:16:0;;:51;;;;43657:7;-1:-1:-1;;;;;43633:31:0;:20;43645:7;43633:11;:20::i;:::-;-1:-1:-1;;;;;43633:31:0;;43613:51;:87;;;;43668:32;43685:5;43692:7;43668:16;:32::i;65610:700::-;65733:5;-1:-1:-1;;;;;65712:26:0;:17;65720:8;65712:7;:17::i;:::-;-1:-1:-1;;;;;65712:26:0;;65704:80;;;;-1:-1:-1;;;65704:80:0;;22636:2:1;65704:80:0;;;22618:21:1;22675:2;22655:18;;;22648:30;22714:34;22694:18;;;22687:62;-1:-1:-1;;;22765:18:1;;;22758:39;22814:19;;65704:80:0;22434:405:1;65704:80:0;-1:-1:-1;;;;;65803:17:0;;65795:66;;;;-1:-1:-1;;;65795:66:0;;18677:2:1;65795:66:0;;;18659:21:1;18716:2;18696:18;;;18689:30;18755:34;18735:18;;;18728:62;-1:-1:-1;;;18806:18:1;;;18799:34;18850:19;;65795:66:0;18475:400:1;65795:66:0;-1:-1:-1;;;;;65950:24:0;;;;;;:19;:24;;;;;:26;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;65987:26:0;;;;;;:19;:26;;;;;:28;;;;;;:::i;:::-;;;;;;66028:42;66049:5;66056:3;66061:8;66028:20;:42::i;:::-;66123:28;;;;:18;:28;;;;;:34;;-1:-1:-1;;;;;;66123:34:0;-1:-1:-1;;;;;66123:34:0;;;;;66222:30;;66123:28;66222:8;:30::i;:::-;66291:8;66286:3;-1:-1:-1;;;;;66270:30:0;66279:5;-1:-1:-1;;;;;66270:30:0;;;;;;;;;;;65610:700;;;:::o;86815:682::-;87138:26;;;;:16;:26;;;;;;;;;:37;;;;-1:-1:-1;;;;;87138:37:0;;;-1:-1:-1;;;;;;87138:37:0;;;;;;;;;;;;;;-1:-1:-1;;;;;87138:37:0;;;-1:-1:-1;;;87138:37:0;;;;;;;;;-1:-1:-1;87138:37:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;87138:37:0;;;-1:-1:-1;;;87138:37:0;-1:-1:-1;;;;;;87138:37:0;;;;;;;;;;;;;;;87197:288;;12460:32:1;;;12442:51;;12509:18;;;12502:34;;;12552:18;;;12545:34;12595:18;;;12588:34;;;;12638:19;;;12631:35;12480:3;12682:19;;12675:35;;;87197:288:0;;12429:3:1;12414:19;87197:288:0;;;;;;;86815:682;;;;:::o;61349:137::-;59180:10;;-1:-1:-1;;;;;59180:10:0;59166;:24;59158:33;;;;;;60787:6:::1;::::0;-1:-1:-1;;;60787:6:0;::::1;;;60779:15;;;::::0;::::1;;61464:6:::2;:14:::0;;-1:-1:-1;;;;61464:14:0::2;::::0;;61349:137::o;87835:2896::-;87931:7;88044:26;;;:16;:26;;;;;91194:18;;;;-1:-1:-1;;;91194:18:0;;-1:-1:-1;;;;;91194:18:0;88369:30;;;;;;88497:13;88513:22;88527:7;88513:13;:22::i;:::-;88497:38;;88572:5;88558:10;:19;;88550:28;;;;;;88628:14;;-1:-1:-1;;;;;88628:14:0;88807:24;88822:8;88807:14;:24::i;:::-;88916:9;;88912:1063;;89141:19;89163:18;89175:5;89163:11;:18::i;:::-;89141:40;-1:-1:-1;89200:22:0;89225:19;89141:40;89225:5;:19;:::i;:::-;89865:10;;89857:41;;89200:44;;-1:-1:-1;;;;;;89865:10:0;;89857:41;;;;;89886:11;;89865:10;89857:41;89865:10;89857:41;89886:11;89865:10;89857:41;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89919:40:0;;-1:-1:-1;;;;;89919:24:0;;;:40;;;;;89944:14;;89919:40;;;;89944:14;89919:24;:40;;;;;;;;;;;;;;;;;;;;;88927:1048;;88912:1063;90290:17;90310:18;90323:5;90310:10;:18;:::i;:::-;90551:39;;90290:38;;-1:-1:-1;90559:10:0;;90551:39;;;;;90290:38;;90551:39;;;;90290:38;90559:10;90551:39;;;;;;;;;;;;;;;;;;;;-1:-1:-1;90644:46:0;;;24863:25:1;;;24919:2;24904:18;;24897:34;;;90679:10:0;24947:18:1;;;24940:60;90644:46:0;;;;;;;24851:2:1;90644:46:0;;;-1:-1:-1;90714:5:0;;87835:2896;-1:-1:-1;;;;;87835:2896:0:o;75839:1337::-;76048:4;76132:10;76118;:24;76114:69;;;-1:-1:-1;76166:5:0;76159:12;;76114:69;76238:14;;:19;;:42;;-1:-1:-1;76261:14:0;;:19;76238:42;76234:87;;;-1:-1:-1;76304:5:0;76297:12;;76234:87;76386:18;;;;-1:-1:-1;;;76386:18:0;;;;:32;;;:68;;-1:-1:-1;76422:18:0;;;;-1:-1:-1;;;76422:18:0;;;;:32;;76386:68;76382:113;;;-1:-1:-1;76478:5:0;76471:12;;76382:113;76509:18;;;;-1:-1:-1;;;76509:18:0;;;;:32;;;:68;;-1:-1:-1;76545:18:0;;;;-1:-1:-1;;;76545:18:0;;;;:32;;76509:68;76505:113;;;-1:-1:-1;76601:5:0;76594:12;;76505:113;76702:18;;;;-1:-1:-1;;;76702:18:0;;;;:23;;:50;;-1:-1:-1;76729:18:0;;;;-1:-1:-1;;;76729:18:0;;;;:23;76702:50;76698:94;;;-1:-1:-1;76776:4:0;76769:11;;76698:94;76887:18;;;;;76865;;;;-1:-1:-1;;;76887:18:0;;;;;;;;76865;;;;;:40;;:84;;-1:-1:-1;76931:18:0;;;;;76909;;;;-1:-1:-1;;;76909:18:0;;76931;76909;;;-1:-1:-1;;;76931:18:0;;;;76909:40;76865:84;76861:129;;;-1:-1:-1;76973:5:0;76966:12;;76861:129;77026:18;;;;;77004;;;;-1:-1:-1;;;77026:18:0;;;;;;;;77004;;;;;:40;;:84;;-1:-1:-1;77070:18:0;;;;;77048;;;;-1:-1:-1;;;77070:18:0;;;;;;;;77048;;;;;:40;77004:84;77000:129;;;-1:-1:-1;77112:5:0;77105:12;;77000:129;-1:-1:-1;77164:4:0;75839:1337;;;;;;:::o;81073:2149::-;81277:4;81664:10;81649:27;;81635:10;:41;81627:50;;;;;;81725:10;81710:27;;81696:10;:41;81688:50;;;;;;81787:11;81772:28;;81757:11;:43;81749:52;;;;;;81881:20;81911:15;81925:1;81911:11;:15;:::i;:::-;81881:46;;81958:2;81942:13;:18;;;81938:69;;;-1:-1:-1;81993:2:0;81938:69;82043:307;;;;;;;;;;;-1:-1:-1;;;;;82111:15:0;82043:307;;;;;;;;82019:21;82043:307;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82385:6;:13;;82409:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;82409:20:0;-1:-1:-1;;;;82409:20:0;;;;-1:-1:-1;;;82409:20:0;;;;;-1:-1:-1;;;;82409:20:0;;;-1:-1:-1;;;82409:20:0;-1:-1:-1;;;;82409:20:0;;;-1:-1:-1;;;82409:20:0;;;;;-1:-1:-1;;;;82409:20:0;;;-1:-1:-1;;;82409:20:0;-1:-1:-1;;;;;;82409:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82043:307;;82385:13;82605:28;;82590:43;;82582:52;;;;;;82752:32;82764:6;82772:11;82752;:32::i;:::-;82910:17;;;;;82951;;;;;82984:13;;82835:245;;;-1:-1:-1;;;;;11812:32:1;;11794:51;;11876:2;11861:18;;11854:34;;;82902:26:0;;;;11904:18:1;;;11897:34;;;;82943:26:0;;;;11947:18:1;;;11940:34;;;;11990:19;;11983:35;12067:6;12055:19;;11832:3;12034:19;;12027:48;-1:-1:-1;;;;;83053:15:0;12112:31:1;12106:3;12091:19;;12084:60;82835:245:0;;11781:3:1;11766:19;82835:245:0;;;;;;;83093:26;83122:6;83129:11;83122:19;;;;;;;;:::i;:::-;;;;;;;;;;;83093:48;;83154:29;83171:11;83154:16;:29::i;:::-;-1:-1:-1;83203:11:0;81073:2149;-1:-1:-1;;;;;;;;81073:2149:0:o;69040:193::-;69167:4;69215:9;-1:-1:-1;;;;;69194:30:0;:17;69202:8;69194:7;:17::i;:::-;-1:-1:-1;;;;;69194:30:0;;;69040:193;-1:-1:-1;;;69040:193:0:o;83621:1373::-;83716:26;83745:6;83752:7;83745:15;;;;;;;;:::i;:::-;;;;;;;;;;;83716:44;;83773:22;83798:6;83805:11;:21;;;;;;;;;;;;83798:29;;;;;;;;;;:::i;:::-;;;;;;;;;;;83773:54;;83838:22;83863:6;83870:11;:21;;;;;;;;;;;;83863:29;;;;;;;;;;:::i;:::-;;;;;;;;83969:21;;;;83863:29;;;;;;-1:-1:-1;83863:29:0;;83969:21;-1:-1:-1;;;83969:21:0;;;;:25;83965:130;;84019:13;;;-1:-1:-1;83965:130:0;;;84074:9;84065:18;;83965:130;84111:21;;;;-1:-1:-1;;;84111:21:0;;;;:25;84107:130;;-1:-1:-1;84161:13:0;;84107:130;;;-1:-1:-1;84216:9:0;84107:130;84307:17;;;;-1:-1:-1;;;;;84307:17:0;:22;;;;:48;;-1:-1:-1;84333:17:0;;;;-1:-1:-1;;;;;84333:17:0;:22;;84307:48;84299:57;;;;;;84432:24;84448:7;84432:15;:24::i;:::-;84424:33;;;;;;84537:17;;:22;84529:31;;;;;;84668:12;;;84708:28;;;;84645:20;;-1:-1:-1;;;;;84668:12:0;;:23;;84692:6;;84700;;84708:32;;84668:12;-1:-1:-1;;;84708:28:0;;-1:-1:-1;;;;;84708:28:0;:32;:::i;:::-;84668:73;;-1:-1:-1;;;;;;84668:73:0;;;;;;;;;;25212:25:1;;;;25253:18;;;25246:34;;;;-1:-1:-1;;;;;25316:31:1;25296:18;;;25289:59;25185:18;;84668:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;84754:41;;;84896:10;;84880:48;;84645:96;;-1:-1:-1;;;;;;84896:10:0;;84918:9;84880:48;;;;;84754:17;84880:48;84754:17;84880:48;84918:9;84896:10;84880:48;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84946:40:0;;;84952:10;10841:51:1;;10923:2;10908:18;;10901:34;;;10951:18;;;10944:34;;;84946:40:0;;10829:2:1;10814:18;84946:40:0;;;;;;;83705:1289;;;;;;83621:1373;;;:::o;78104:1180::-;78181:7;78255:22;78280:6;78287:10;78280:18;;;;;;;;:::i;:::-;;;;;;;;;;;78255:43;;78309:22;78334:6;78341:10;78334:18;;;;;;;;:::i;:::-;;;;;;;;;78454;;;;;78334;;;;;;;78487;;;;78334;;-1:-1:-1;78454:18:0;-1:-1:-1;;;78454:18:0;;;;;;;78487;;;;:39;-1:-1:-1;78483:102:0;;;-1:-1:-1;78555:18:0;;;;-1:-1:-1;;;78555:18:0;;;;78483:102;78734:10;;78718:55;;78624:9;;-1:-1:-1;;;;;78734:10:0;;78718:55;;;;;78624:9;;78597:24;78718:55;78597:24;78718:55;78624:9;78734:10;78718:55;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78817:13:0;78833:30;;;:18;:30;;;;;;-1:-1:-1;;;;;78833:30:0;;78894:62;78852:10;78920;78932:13;:9;78833:30;78932:13;:::i;:::-;78894:62;;78947:1;78950:5;78894:13;:62::i;:::-;78874:82;;79020:25;79037:7;79020:16;:25::i;:::-;79056;79073:7;79056:16;:25::i;:::-;79155:30;;;;:18;:30;;;;;;;;;;;79222:24;;;79136:111;;-1:-1:-1;;;;;79155:30:0;;;12978:51:1;;13045:18;;;13038:34;;;13088:18;;;13081:34;;;13146:2;13131:18;;13124:34;;;-1:-1:-1;;;79222:24:0;;-1:-1:-1;;;;;79222:24:0;13189:3:1;13174:19;;13167:60;79136:111:0;;12965:3:1;12950:19;79136:111:0;;;;;;;79267:9;78104:1180;-1:-1:-1;;;;;;;;78104:1180:0:o;18262:173::-;18337:6;;;-1:-1:-1;;;;;18354:17:0;;;-1:-1:-1;;;;;;18354:17:0;;;;;;;18387:40;;18337:6;;;18354:17;18337:6;;18387:40;;18318:16;;18387:40;18307:128;18262:173;:::o;72382:203::-;72446:4;72463:26;72492:6;72499:7;72492:15;;;;;;;;:::i;:::-;;;;;;;;;72525:28;72492:15;;;;;72525:28;;-1:-1:-1;;;;;72564:12:0;72525:52;;-1:-1:-1;;;72525:28:0;;;;:52;;;72382:203;-1:-1:-1;;;72382:203:0:o;87563:148::-;87629:24;87644:8;87629:14;:24::i;:::-;87673:26;;14979:25:1;;;87673:26:0;;14967:2:1;14952:18;87673:26:0;;;;;;;87563:148;:::o;42439:315::-;42596:28;42606:4;42612:2;42616:7;42596:9;:28::i;:::-;42643:48;42666:4;42672:2;42676:7;42685:5;42643:22;:48::i;:::-;42635:111;;;;-1:-1:-1;;;42635:111:0;;;;;;;:::i;91550:741::-;91966:18;;;;91661:7;;;;-1:-1:-1;;;91966:18:0;;-1:-1:-1;;;;;91966:18:0;91948:15;:36;91944:129;;;92039:18;;;;92021:36;;-1:-1:-1;;;92039:18:0;;-1:-1:-1;;;;;92039:18:0;92021:15;:36;:::i;:::-;92005:52;;91944:129;92135:22;;;;92215:17;;;;92096:183;;-1:-1:-1;;;;;92135:22:0;;;;-1:-1:-1;;;92176:20:0;;;;;-1:-1:-1;;;;;92215:17:0;92251:13;92096:20;:183::i;13566:723::-;13622:13;13843:10;13839:53;;-1:-1:-1;;13870:10:0;;;;;;;;;;;;-1:-1:-1;;;13870:10:0;;;;;13566:723::o;13839:53::-;13917:5;13902:12;13958:78;13965:9;;13958:78;;13991:8;;;;:::i;:::-;;-1:-1:-1;14014:10:0;;-1:-1:-1;14022:2:0;14014:10;;:::i;:::-;;;13958:78;;;14046:19;14078:6;-1:-1:-1;;;;;14068:17:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;14068:17:0;;14046:39;;14096:154;14103:10;;14096:154;;14130:11;14140:1;14130:11;;:::i;:::-;;-1:-1:-1;14199:10:0;14207:2;14199:5;:10;:::i;:::-;14186:24;;:2;:24;:::i;:::-;14173:39;;14156:6;14163;14156:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;14156:56:0;;;;;;;;-1:-1:-1;14227:11:0;14236:2;14227:11;;:::i;:::-;;;14096:154;;12229:410;12339:7;10406:100;;;;;;;;;;;;;;;;;10386:127;;;;;;;12493:12;;12528:11;;;;12572:24;;;;;12562:35;;;;;;12412:204;;;;;15246:25:1;;;15302:2;15287:18;;15280:34;;;;-1:-1:-1;;;;;15350:32:1;15345:2;15330:18;;15323:60;15414:2;15399:18;;15392:34;15233:3;15218:19;;15015:417;12412:204:0;;;;;;;;;;;;;12384:247;;;;;;12364:267;;12229:410;;;:::o;2166:258::-;2265:7;2367:20;1605:15;;;1527:101;2367:20;2338:63;;-1:-1:-1;;;2338:63:0;;;9363:27:1;9406:11;;;9399:27;;;;9442:12;;;9435:28;;;9479:12;;2338:63:0;9105:392:1;51898:589:0;-1:-1:-1;;;;;52104:18:0;;52100:187;;52139:40;52171:7;53314:10;:17;;53287:24;;;;:15;:24;;;;;:44;;;53342:24;;;;;;;;;;;;53210:164;52139:40;52100:187;;;52209:2;-1:-1:-1;;;;;52201:10:0;:4;-1:-1:-1;;;;;52201:10:0;;52197:90;;52228:47;52261:4;52267:7;52228:32;:47::i;:::-;-1:-1:-1;;;;;52301:16:0;;52297:183;;52334:45;52371:7;52334:36;:45::i;52297:183::-;52407:4;-1:-1:-1;;;;;52401:10:0;:2;-1:-1:-1;;;;;52401:10:0;;52397:83;;52428:40;52456:2;52460:7;52428:27;:40::i;90865:111::-;90938:26;;;;:16;:26;;;;;90931:33;;-1:-1:-1;;;;;;90931:33:0;;;;;;;;;;;;;;-1:-1:-1;;;;;;90931:33:0;;;90865:111::o;94451:517::-;94511:7;94951:5;94940:8;;94931:6;:17;;;;:::i;:::-;:25;;;;:::i;68265:295::-;68337:20;68343:3;68348:8;68337:5;:20::i;:::-;-1:-1:-1;;;;;68448:24:0;;;;;;:19;:24;;;;;:26;;;;;;:::i;:::-;;;;-1:-1:-1;;68518:28:0;;;;:18;:28;;;;;:34;;-1:-1:-1;;;;;;68518:34:0;-1:-1:-1;;;;;68518:34:0;;;;;;;;;;68265:295::o;73361:612::-;73601:15;;73577:22;;;;73620:12;;73601:15;73567:9;;-1:-1:-1;;;73577:22:0;;;;73567:33;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;:49;;;;;;:::i;:::-;73566:66;;;;:::i;:::-;73531:25;;;:102;;-1:-1:-1;;73531:102:0;-1:-1:-1;;;;;;;;73531:102:0;;;;;;;;;;;;;;;;73908:2;-1:-1:-1;;;73883:22:0;;;;;:27;73879:87;;;73953:1;73927:22;;;:27;;:22;;:27;;73953:1;;-1:-1:-1;;;73927:27:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;73361:612;:::o;47788:799::-;47943:4;-1:-1:-1;;;;;47964:13:0;;19531:20;19579:8;47960:620;;48016:2;-1:-1:-1;;;;;48000:36:0;;48037:12;:10;:12::i;:::-;48051:4;48057:7;48066:5;48000:72;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48000:72:0;;;;;;;;-1:-1:-1;;48000:72:0;;;;;;;;;;;;:::i;:::-;;;47996:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48242:13:0;;48238:272;;48285:60;;-1:-1:-1;;;48285:60:0;;;;;;;:::i;48238:272::-;48460:6;48454:13;48445:6;48441:2;48437:15;48430:38;47996:529;-1:-1:-1;;;;;;48123:51:0;-1:-1:-1;;;48123:51:0;;-1:-1:-1;48116:58:0;;47960:620;-1:-1:-1;48564:4:0;48557:11;;92565:1776;92809:7;93211:9;93193:14;:27;93189:1141;;-1:-1:-1;93384:12:0;93377:19;;93189:1141;93572:23;93598:45;93628:14;93605:12;93598:45;:::i;:::-;93572:71;-1:-1:-1;93908:25:0;93987:9;93936:41;93962:14;93572:71;93936:41;:::i;:::-;:61;;;;:::i;:::-;93908:89;-1:-1:-1;94200:19:0;94222:43;93908:89;94229:14;94222:43;:::i;:::-;94200:65;-1:-1:-1;94286:28:0;;-1:-1:-1;;;94286:28:0;54001:988;54267:22;54317:1;54292:22;54309:4;54292:16;:22::i;:::-;:26;;;;:::i;:::-;54329:18;54350:26;;;:17;:26;;;;;;54267:51;;-1:-1:-1;54483:28:0;;;54479:328;;-1:-1:-1;;;;;54550:18:0;;54528:19;54550:18;;;:12;:18;;;;;;;;:34;;;;;;;;;54601:30;;;;;;:44;;;54718:30;;:17;:30;;;;;:43;;;54479:328;-1:-1:-1;54903:26:0;;;;:17;:26;;;;;;;;54896:33;;;-1:-1:-1;;;;;54947:18:0;;;;;:12;:18;;;;;:34;;;;;;;54940:41;54001:988::o;55284:1079::-;55562:10;:17;55537:22;;55562:21;;55582:1;;55562:21;:::i;:::-;55594:18;55615:24;;;:15;:24;;;;;;55988:10;:26;;55537:46;;-1:-1:-1;55615:24:0;;55537:46;;55988:26;;;;;;:::i;:::-;;;;;;;;;55966:48;;56052:11;56027:10;56038;56027:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;56132:28;;;:15;:28;;;;;;;:41;;;56304:24;;;;;56297:31;56339:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;55355:1008;;;55284:1079;:::o;52788:221::-;52873:14;52890:20;52907:2;52890:16;:20::i;:::-;-1:-1:-1;;;;;52921:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;52966:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;52788:221:0:o;45045:382::-;-1:-1:-1;;;;;45125:16:0;;45117:61;;;;-1:-1:-1;;;45117:61:0;;21501:2:1;45117:61:0;;;21483:21:1;;;21520:18;;;21513:30;21579:34;21559:18;;;21552:62;21631:18;;45117:61:0;21299:356:1;45117:61:0;43132:4;43156:16;;;:7;:16;;;;;;-1:-1:-1;;;;;43156:16:0;:30;45189:58;;;;-1:-1:-1;;;45189:58:0;;18320:2:1;45189:58:0;;;18302:21:1;18359:2;18339:18;;;18332:30;18398;18378:18;;;18371:58;18446:18;;45189:58:0;18118:352:1;45189:58:0;45260:45;45289:1;45293:2;45297:7;45260:20;:45::i;:::-;-1:-1:-1;;;;;45318:13:0;;;;;;:9;:13;;;;;:18;;45335:1;;45318:13;:18;;45335:1;;45318:18;:::i;:::-;;;;-1:-1:-1;;45347:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;45347:21:0;-1:-1:-1;;;;;45347:21:0;;;;;;;;45386:33;;45347:16;;;45386:33;;45347:16;;45386:33;45045:382;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:631:1;78:5;-1:-1:-1;;;;;149:2:1;141:6;138:14;135:40;;;155:18;;:::i;:::-;230:2;224:9;198:2;284:15;;-1:-1:-1;;280:24:1;;;306:2;276:33;272:42;260:55;;;330:18;;;350:22;;;327:46;324:72;;;376:18;;:::i;:::-;416:10;412:2;405:22;445:6;436:15;;475:6;467;460:22;515:3;506:6;501:3;497:16;494:25;491:45;;;532:1;529;522:12;491:45;582:6;577:3;570:4;562:6;558:17;545:44;637:1;630:4;621:6;613;609:19;605:30;598:41;;;;14:631;;;;;:::o;650:220::-;692:5;745:3;738:4;730:6;726:17;722:27;712:55;;763:1;760;753:12;712:55;785:79;860:3;851:6;838:20;831:4;823:6;819:17;785:79;:::i;875:247::-;934:6;987:2;975:9;966:7;962:23;958:32;955:52;;;1003:1;1000;993:12;955:52;1042:9;1029:23;1061:31;1086:5;1061:31;:::i;1387:388::-;1455:6;1463;1516:2;1504:9;1495:7;1491:23;1487:32;1484:52;;;1532:1;1529;1522:12;1484:52;1571:9;1558:23;1590:31;1615:5;1590:31;:::i;:::-;1640:5;-1:-1:-1;1697:2:1;1682:18;;1669:32;1710:33;1669:32;1710:33;:::i;:::-;1762:7;1752:17;;;1387:388;;;;;:::o;1780:456::-;1857:6;1865;1873;1926:2;1914:9;1905:7;1901:23;1897:32;1894:52;;;1942:1;1939;1932:12;1894:52;1981:9;1968:23;2000:31;2025:5;2000:31;:::i;:::-;2050:5;-1:-1:-1;2107:2:1;2092:18;;2079:32;2120:33;2079:32;2120:33;:::i;:::-;1780:456;;2172:7;;-1:-1:-1;;;2226:2:1;2211:18;;;;2198:32;;1780:456::o;2241:665::-;2336:6;2344;2352;2360;2413:3;2401:9;2392:7;2388:23;2384:33;2381:53;;;2430:1;2427;2420:12;2381:53;2469:9;2456:23;2488:31;2513:5;2488:31;:::i;:::-;2538:5;-1:-1:-1;2595:2:1;2580:18;;2567:32;2608:33;2567:32;2608:33;:::i;:::-;2660:7;-1:-1:-1;2714:2:1;2699:18;;2686:32;;-1:-1:-1;2769:2:1;2754:18;;2741:32;-1:-1:-1;;;;;2785:30:1;;2782:50;;;2828:1;2825;2818:12;2782:50;2851:49;2892:7;2883:6;2872:9;2868:22;2851:49;:::i;:::-;2841:59;;;2241:665;;;;;;;:::o;2911:382::-;2976:6;2984;3037:2;3025:9;3016:7;3012:23;3008:32;3005:52;;;3053:1;3050;3043:12;3005:52;3092:9;3079:23;3111:31;3136:5;3111:31;:::i;:::-;3161:5;-1:-1:-1;3218:2:1;3203:18;;3190:32;3231:30;3190:32;3231:30;:::i;3298:758::-;3400:6;3408;3416;3424;3432;3485:3;3473:9;3464:7;3460:23;3456:33;3453:53;;;3502:1;3499;3492:12;3453:53;3541:9;3528:23;3560:31;3585:5;3560:31;:::i;:::-;3610:5;-1:-1:-1;3666:2:1;3651:18;;3638:32;-1:-1:-1;;;;;3682:30:1;;3679:50;;;3725:1;3722;3715:12;3679:50;3748:49;3789:7;3780:6;3769:9;3765:22;3748:49;:::i;:::-;3738:59;;;3844:2;3833:9;3829:18;3816:32;3806:42;;3895:2;3884:9;3880:18;3867:32;3857:42;;3951:3;3940:9;3936:19;3923:33;4000:4;3991:7;3987:18;3978:7;3975:31;3965:59;;4020:1;4017;4010:12;3965:59;4043:7;4033:17;;;3298:758;;;;;;;;:::o;4061:315::-;4129:6;4137;4190:2;4178:9;4169:7;4165:23;4161:32;4158:52;;;4206:1;4203;4196:12;4158:52;4245:9;4232:23;4264:31;4289:5;4264:31;:::i;:::-;4314:5;4366:2;4351:18;;;;4338:32;;-1:-1:-1;;;4061:315:1:o;4381:245::-;4448:6;4501:2;4489:9;4480:7;4476:23;4472:32;4469:52;;;4517:1;4514;4507:12;4469:52;4549:9;4543:16;4568:28;4590:5;4568:28;:::i;4631:245::-;4689:6;4742:2;4730:9;4721:7;4717:23;4713:32;4710:52;;;4758:1;4755;4748:12;4710:52;4797:9;4784:23;4816:30;4840:5;4816:30;:::i;4881:249::-;4950:6;5003:2;4991:9;4982:7;4978:23;4974:32;4971:52;;;5019:1;5016;5009:12;4971:52;5051:9;5045:16;5070:30;5094:5;5070:30;:::i;5135:280::-;5234:6;5287:2;5275:9;5266:7;5262:23;5258:32;5255:52;;;5303:1;5300;5293:12;5255:52;5335:9;5329:16;5354:31;5379:5;5354:31;:::i;5420:450::-;5489:6;5542:2;5530:9;5521:7;5517:23;5513:32;5510:52;;;5558:1;5555;5548:12;5510:52;5598:9;5585:23;-1:-1:-1;;;;;5623:6:1;5620:30;5617:50;;;5663:1;5660;5653:12;5617:50;5686:22;;5739:4;5731:13;;5727:27;-1:-1:-1;5717:55:1;;5768:1;5765;5758:12;5717:55;5791:73;5856:7;5851:2;5838:16;5833:2;5829;5825:11;5791:73;:::i;5875:180::-;5934:6;5987:2;5975:9;5966:7;5962:23;5958:32;5955:52;;;6003:1;6000;5993:12;5955:52;-1:-1:-1;6026:23:1;;5875:180;-1:-1:-1;5875:180:1:o;6060:184::-;6130:6;6183:2;6171:9;6162:7;6158:23;6154:32;6151:52;;;6199:1;6196;6189:12;6151:52;-1:-1:-1;6222:16:1;;6060:184;-1:-1:-1;6060:184:1:o;6249:315::-;6317:6;6325;6378:2;6366:9;6357:7;6353:23;6349:32;6346:52;;;6394:1;6391;6384:12;6346:52;6430:9;6417:23;6407:33;;6490:2;6479:9;6475:18;6462:32;6503:31;6528:5;6503:31;:::i;6569:248::-;6637:6;6645;6698:2;6686:9;6677:7;6673:23;6669:32;6666:52;;;6714:1;6711;6704:12;6666:52;-1:-1:-1;;6737:23:1;;;6807:2;6792:18;;;6779:32;;-1:-1:-1;6569:248:1:o;6822:316::-;6899:6;6907;6915;6968:2;6956:9;6947:7;6943:23;6939:32;6936:52;;;6984:1;6981;6974:12;6936:52;-1:-1:-1;;7007:23:1;;;7077:2;7062:18;;7049:32;;-1:-1:-1;7128:2:1;7113:18;;;7100:32;;6822:316;-1:-1:-1;6822:316:1:o;7143:521::-;7238:6;7246;7254;7262;7270;7323:3;7311:9;7302:7;7298:23;7294:33;7291:53;;;7340:1;7337;7330:12;7291:53;7376:9;7363:23;7353:33;;7433:2;7422:9;7418:18;7405:32;7395:42;;7484:2;7473:9;7469:18;7456:32;7446:42;;7535:2;7524:9;7520:18;7507:32;7497:42;;7589:3;7578:9;7574:19;7561:33;7603:31;7628:5;7603:31;:::i;7669:257::-;7710:3;7748:5;7742:12;7775:6;7770:3;7763:19;7791:63;7847:6;7840:4;7835:3;7831:14;7824:4;7817:5;7813:16;7791:63;:::i;:::-;7908:2;7887:15;-1:-1:-1;;7883:29:1;7874:39;;;;7915:4;7870:50;;7669:257;-1:-1:-1;;7669:257:1:o;7931:274::-;8060:3;8098:6;8092:13;8114:53;8160:6;8155:3;8148:4;8140:6;8136:17;8114:53;:::i;:::-;8183:16;;;;;7931:274;-1:-1:-1;;7931:274:1:o;8210:415::-;8367:3;8405:6;8399:13;8421:53;8467:6;8462:3;8455:4;8447:6;8443:17;8421:53;:::i;:::-;8543:2;8539:15;;;;-1:-1:-1;;8535:53:1;8496:16;;;;8521:68;;;8616:2;8605:14;;8210:415;-1:-1:-1;;8210:415:1:o;8630:470::-;8809:3;8847:6;8841:13;8863:53;8909:6;8904:3;8897:4;8889:6;8885:17;8863:53;:::i;:::-;8979:13;;8938:16;;;;9001:57;8979:13;8938:16;9035:4;9023:17;;9001:57;:::i;:::-;9074:20;;8630:470;-1:-1:-1;;;;8630:470:1:o;9710:431::-;-1:-1:-1;;;;;9967:15:1;;;9949:34;;10019:15;;10014:2;9999:18;;9992:43;10071:2;10066;10051:18;;10044:30;;;9892:4;;10091:44;;10116:18;;10108:6;10091:44;:::i;10146:488::-;-1:-1:-1;;;;;10415:15:1;;;10397:34;;10467:15;;10462:2;10447:18;;10440:43;10514:2;10499:18;;10492:34;;;10562:3;10557:2;10542:18;;10535:31;;;10340:4;;10583:45;;10608:19;;10600:6;10583:45;:::i;:::-;10575:53;10146:488;-1:-1:-1;;;;;;10146:488:1:o;13238:632::-;13409:2;13461:21;;;13531:13;;13434:18;;;13553:22;;;13380:4;;13409:2;13632:15;;;;13606:2;13591:18;;;13380:4;13675:169;13689:6;13686:1;13683:13;13675:169;;;13750:13;;13738:26;;13819:15;;;;13784:12;;;;13711:1;13704:9;13675:169;;;-1:-1:-1;13861:3:1;;13238:632;-1:-1:-1;;;;;;13238:632:1:o;15840:217::-;15987:2;15976:9;15969:21;15950:4;16007:44;16047:2;16036:9;16032:18;16024:6;16007:44;:::i;16935:414::-;17137:2;17119:21;;;17176:2;17156:18;;;17149:30;17215:34;17210:2;17195:18;;17188:62;-1:-1:-1;;;17281:2:1;17266:18;;17259:48;17339:3;17324:19;;16935:414::o;20478:406::-;20680:2;20662:21;;;20719:2;20699:18;;;20692:30;20758:34;20753:2;20738:18;;20731:62;-1:-1:-1;;;20824:2:1;20809:18;;20802:40;20874:3;20859:19;;20478:406::o;22073:356::-;22275:2;22257:21;;;22294:18;;;22287:30;22353:34;22348:2;22333:18;;22326:62;22420:2;22405:18;;22073:356::o;23648:413::-;23850:2;23832:21;;;23889:2;23869:18;;;23862:30;23928:34;23923:2;23908:18;;23901:62;-1:-1:-1;;;23994:2:1;23979:18;;23972:47;24051:3;24036:19;;23648:413::o;25556:265::-;25595:3;25623:9;;;25648:10;;-1:-1:-1;;;;;25667:27:1;;;25660:35;;25644:52;25641:78;;;25699:18;;:::i;:::-;-1:-1:-1;;;25746:19:1;;;25739:27;;25731:36;;25728:62;;;25770:18;;:::i;:::-;-1:-1:-1;;25806:9:1;;25556:265::o;25826:224::-;25865:3;25893:6;25926:2;25923:1;25919:10;25956:2;25953:1;25949:10;25987:3;25983:2;25979:12;25974:3;25971:21;25968:47;;;25995:18;;:::i;26055:128::-;26095:3;26126:1;26122:6;26119:1;26116:13;26113:39;;;26132:18;;:::i;:::-;-1:-1:-1;26168:9:1;;26055:128::o;26188:193::-;26227:1;26253;26243:35;;26258:18;;:::i;:::-;-1:-1:-1;;;26294:18:1;;-1:-1:-1;;26314:13:1;;26290:38;26287:64;;;26331:18;;:::i;:::-;-1:-1:-1;26365:10:1;;26188:193::o;26386:120::-;26426:1;26452;26442:35;;26457:18;;:::i;:::-;-1:-1:-1;26491:9:1;;26386:120::o;26511:553::-;26550:7;-1:-1:-1;;;;;26620:9:1;;;26648;;;26673:11;;;26692:10;;;26686:17;;26669:35;26666:61;;;26707:18;;:::i;:::-;-1:-1:-1;;;26783:1:1;26776:9;;26801:11;;;26821;;;26814:19;;26797:37;26794:63;;;26837:18;;:::i;:::-;26883:1;26880;26876:9;26866:19;;26930:1;26926:2;26921:11;26918:1;26914:19;26909:2;26905;26901:11;26897:37;26894:63;;;26937:18;;:::i;:::-;27002:1;26998:2;26993:11;26990:1;26986:19;26981:2;26977;26973:11;26969:37;26966:63;;;27009:18;;:::i;:::-;-1:-1:-1;;;27049:9:1;;;;;26511:553;-1:-1:-1;;;26511:553:1:o;27069:168::-;27109:7;27175:1;27171;27167:6;27163:14;27160:1;27157:21;27152:1;27145:9;27138:17;27134:45;27131:71;;;27182:18;;:::i;:::-;-1:-1:-1;27222:9:1;;27069:168::o;27242:267::-;27281:4;27310:9;;;27335:10;;-1:-1:-1;;;27354:19:1;;27347:27;;27331:44;27328:70;;;27378:18;;:::i;:::-;-1:-1:-1;;;;;27425:27:1;;27418:35;;27410:44;;27407:70;;;27457:18;;:::i;:::-;-1:-1:-1;;27494:9:1;;27242:267::o;27514:125::-;27554:4;27582:1;27579;27576:8;27573:34;;;27587:18;;:::i;:::-;-1:-1:-1;27624:9:1;;27514:125::o;27644:229::-;27683:4;-1:-1:-1;;;;;27780:10:1;;;;27750;;27802:12;;;27799:38;;;27817:18;;:::i;:::-;27854:13;;27644:229;-1:-1:-1;;;27644:229:1:o;27878:258::-;27950:1;27960:113;27974:6;27971:1;27968:13;27960:113;;;28050:11;;;28044:18;28031:11;;;28024:39;27996:2;27989:10;27960:113;;;28091:6;28088:1;28085:13;28082:48;;;-1:-1:-1;;28126:1:1;28108:16;;28101:27;27878:258::o;28141:136::-;28180:3;28208:5;28198:39;;28217:18;;:::i;:::-;-1:-1:-1;;;28253:18:1;;28141:136::o;28282:380::-;28361:1;28357:12;;;;28404;;;28425:61;;28479:4;28471:6;28467:17;28457:27;;28425:61;28532:2;28524:6;28521:14;28501:18;28498:38;28495:161;;;28578:10;28573:3;28569:20;28566:1;28559:31;28613:4;28610:1;28603:15;28641:4;28638:1;28631:15;28667:135;28706:3;-1:-1:-1;;28727:17:1;;28724:43;;;28747:18;;:::i;:::-;-1:-1:-1;28794:1:1;28783:13;;28667:135::o;28807:112::-;28839:1;28865;28855:35;;28870:18;;:::i;:::-;-1:-1:-1;28904:9:1;;28807:112::o;28924:127::-;28985:10;28980:3;28976:20;28973:1;28966:31;29016:4;29013:1;29006:15;29040:4;29037:1;29030:15;29056:127;29117:10;29112:3;29108:20;29105:1;29098:31;29148:4;29145:1;29138:15;29172:4;29169:1;29162:15;29188:127;29249:10;29244:3;29240:20;29237:1;29230:31;29280:4;29277:1;29270:15;29304:4;29301:1;29294:15;29320:127;29381:10;29376:3;29372:20;29369:1;29362:31;29412:4;29409:1;29402:15;29436:4;29433:1;29426:15;29452:127;29513:10;29508:3;29504:20;29501:1;29494:31;29544:4;29541:1;29534:15;29568:4;29565:1;29558:15;29584:131;-1:-1:-1;;;;;29659:31:1;;29649:42;;29639:70;;29705:1;29702;29695:12;29720:118;29806:5;29799:13;29792:21;29785:5;29782:32;29772:60;;29828:1;29825;29818:12;29843:131;-1:-1:-1;;;;;;29917:32:1;;29907:43;;29897:71;;29964:1;29961;29954:12

Swarm Source

ipfs://70b45eda88a8feb483a94a2759c4a46b69cd8c0bbd18b3c970990c8b5985e22b
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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