ETH Price: $2,524.70 (+0.01%)

Token

BitKoi (BITKOI)
 

Overview

Max Total Supply

214 BITKOI

Holders

89

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
7 BITKOI
0x8fbafa3f17cb155c84915702e331146bda2c53f7
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-11-21
*/

// 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, which includes the logic to enforce a "promo gene" in future gen0 releases
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, uint8 promoGene, uint256 targetBlock) virtual public returns (uint256);
}

/// @title A facet of BitKoiCore that manages special access privileges.
/// Based on work from Cryptokitties and 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
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(uint256 fishId, uint64 timestamp);

    /*** DATA TYPES ***/

    struct BitKoi {
        //a promotional gene that, when active, will enable this bitKoi to hatch with a specific trait
        //this is ONLY assigned for gen0 promo events
        uint8 promoGene;

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

        // The timestamp from the block when this fish was hatched. This also masks the traits for 'unhatched' BitKoi
        uint64 hatchTime;

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

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

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

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

    /// @notice Returns a list of all BitKoi IDs assigned to an address.
    /// @param _owner The owner whose BitKoi we are interested in.
    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 resultIndex = 0;
            uint256 tokenIndex;

            for (tokenIndex = 0; tokenIndex <= tokenCount - 1; tokenIndex++) {
                uint256 tokenId = tokenOfOwnerByIndex(_owner, tokenIndex);
                result[resultIndex] = tokenId;
                resultIndex++;
            }

            return result;
        }
    }
}

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

    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 it to be and not some random other one
        require(candidateContract.isBitKoiTraits());

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

    /// @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 onlyCOO {
        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 onlyCOO {
        hatchFee = val;
    }

    /// @notice Checks that a given fish is able to breed (i.e. it is not
    ///  in the middle of a 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);
    }

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

        //they both have to be hatched
        if (_parent1.hatchTime == 0 || _parent2.hatchTime == 0) {
            return false;
        }

        // Fish can't breed with their parents.
        if (_parent1.parent1Id == _parent2Id || _parent1.parent2Id == _parent2Id) {
            return false;
        }
        if (_parent2.parent1Id == _parent1Id || _parent2.parent2Id == _parent1Id) {
            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.parent2Id == _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. 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 (aka 'grinding nemo'). Assumes that all breeding
    /// requirements have been checked.
    function _breedWith(uint256 _parent1Id, uint256 _parent2Id) internal returns(uint256) {
       
        // Grab a reference to the two Bitkoi we want to breed from storage.
        BitKoi storage parent1 = bitKoi[_parent1Id];
        BitKoi storage parent2 = bitKoi[_parent2Id];

        // Determine the higher generation number of the two parents and use this for the new BitKoi
        uint16 parentGen = parent1.generation;
        if (parent2.generation > parent1.generation) {
            parentGen = parent2.generation;
        }

        // Transfer the breed fee to the CFO contract
        payable(address(cfoAddress)).transfer(msg.value);

        // Get new genes for the bitkoi but don't send in a promo gene - that's only for gen0 eggs
        uint256 newGenes = bitKoiTraits.smooshFish(parent1.genes, parent2.genes, 0, parent1.cooldownEndBlock);

        // Use the genes we just got to create a brand new BitKoi!
        uint256 newFishId = _createBitKoi(_parent1Id, _parent2Id, parentGen + 1, newGenes, false, 0, msg.sender);

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

        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 bitkoi
        require(_owns(msg.sender, _parent1Id));
        require(_owns(msg.sender, _parent2Id));

        // Grab a reference to the bitkoi 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 bitkoi was bred
        require(_isReadyToBreed(parent2));

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

        // All checks passed, smoosh 'em!
        _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 _promoGene The promo gene for special mint events
    /// @param _to 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,
        bool _hatchMe,
        uint8 _promoGene,
        address _to
    )
        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;
        }

        uint64 hatchTime;

        if (_hatchMe){
            hatchTime = uint64(block.timestamp);
        }

        BitKoi memory _bitKoi = BitKoi({
            genes: _genes,
            promoGene: uint8(_promoGene),
            spawnTime: uint64(block.timestamp),
            hatchTime: hatchTime,
            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 required per ERC721
        _safeMint(_to, newBitKoiId);

        // emit the spawn event
        emit Spawn(
            newBitKoiId,
            uint64(_bitKoi.spawnTime)
        );

        return newBitKoiId;
    }

    function hatchBitKoi(uint256 _fishId)
        external
        payable
        whenNotPaused
    {
        // Check for payment.
        require(msg.value >= hatchFee);

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

        BitKoi storage fishToHatch = bitKoi[_fishId];

        // Check to make sure the BitKoi isn't hatched yet
        require(fishToHatch.hatchTime == 0);

        fishToHatch.hatchTime = uint64(block.timestamp);

        // Transfer the hatch fee to the CFO contract
        payable(address(cfoAddress)).transfer(msg.value);
        
        // Announce that a new bitkoi has been hatched and trigger the render of the new asset
        emit Hatch(msg.sender, _fishId, fishToHatch.hatchTime);
    }
}


/// @title all functions related to creating fish (and their eggs)
abstract contract BitKoiMinting is BitKoiBreeding {
    
    // Limits the number of fish the contract owner can ever create.
    uint256 public constant PROMO_CREATION_LIMIT = 5200;
    uint256 public constant GEN0_EGG_CREATION_LIMIT = 44800;

    // Counts the number of bitkoi the contract owner has minted.
    uint256 public promoCreatedCount;
    
    // Counts the number of bitkoi minted in public/private sales and releases
    uint256 public gen0CreatedCount;

    // Minting is not live to start
    bool public allowMinting = false;

    // Mint passes are not required to start
    bool public requireMintPass = false;

    // Require an address to have a token to mint
    uint public requiredHoldings = 0;

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

    // Set the cap of gen0 eggs - will increase progressively as mint events happen for releases
    uint256 public currentGen0Cap = 100;

    // The time the most current mint was started
    uint public mintEventStarted = block.timestamp;

    // The limit per wallet for this period
    uint public currentMintLimit = 0;

    mapping (address => uint) tokensAllowed;
    
    mapping (address => uint) lastMintParticipated;
    
    mapping (address => uint) tokensMintedThisPeriod;

    // allow direct sales of gen0 eggs
    function setAllowMinting(bool _val) external onlyCLevel {
         allowMinting = _val;
    }
    
    // update whether or not holders are required to mint
    function resetMintEventClock() external onlyCLevel {
       mintEventStarted = block.timestamp;
    }

    // update whether or not holders are required to mint
    function setHolderRequirement(uint _val) external onlyCLevel {
        requiredHoldings = _val;
    }

    // set current cap for sale - this can be raised later so new sales can be started w/ limits
    function setCurrentGen0Cap(uint256 _val) external onlyCOO {
        require (gen0CreatedCount + _val <= GEN0_EGG_CREATION_LIMIT);
        currentGen0Cap = _val;
    }

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

    // @dev Updates the max number of items an address can mint in the given period. Can only
    ///  be called by the CEO address.
    function setRequireMintPasses(bool _val) external onlyCOO {
        requireMintPass = _val;
    }
    
    // Here we can limit the number of BitKoi eggs a wallet can mint in the current period
    function setMintLimitPerPeriod(uint _val) external onlyCOO {
        currentMintLimit = _val;
    }

    //set a gene that is promotional and garaunteed to be in a newly hatched egg during the promo period
    uint8 public currentPromoGene = 0;

    //enable the promo gene for future releases
    bool public currentPromoActive = false;

    function setPromoGene(uint8 _val) external onlyCLevel {
        currentPromoGene = _val;
    }

    function setPromoStatus(bool _status) external onlyCLevel {
        currentPromoActive = _status;
    }

    function whitelistMintPasses(address[] calldata _addressList, uint numberOfPasses) external onlyCOO {
        for (uint i = 0; i < _addressList.length; i++) {
            tokensAllowed[_addressList[i]] += numberOfPasses;
        }
    }

    function getAvailablePasses(address _address) public view returns(uint) {
       return tokensAllowed[_address];
    }
    
    function getMintedThisPeriod(address _address) public view returns(uint){
        return tokensMintedThisPeriod[_address];
    }
    
    function getLastMintParticipated(address _address) public view returns(uint){
        return lastMintParticipated[_address];
    }

    function mintGen0Egg(uint numberToMint) 
        external 
        payable 
        whenNotPaused {
        //make sure minting is active
        require (allowMinting);

        //ensure they're trying to mint at least 1 egg just so people don't waste gas
        require(numberToMint > 0);

        //make sure enough eth has been sent
        require (msg.value >= gen0PromoPrice * numberToMint);

        //make sure the new tokens will not exceed the overall cap
        require (gen0CreatedCount + numberToMint <= currentGen0Cap);

        //make sure we aren't over the limit for all gen0Eggs
        require (gen0CreatedCount + numberToMint <= GEN0_EGG_CREATION_LIMIT);

        // require the purchasesr to have at least the number of required tokens to mint
        require (balanceOf(msg.sender) >= requiredHoldings);

        //if a mint pass is required, ensure that they are whitelisted
        if (requireMintPass){
            require(numberToMint <= tokensAllowed[msg.sender]);
        }
        
        //if the last mint they participated in was before this one, then clear the tokens minted for the current period
        if (lastMintParticipated[msg.sender] < mintEventStarted){
            tokensMintedThisPeriod[msg.sender] = 0;
        }
        
        // check to see if they've minted in the current mint period
        if (currentMintLimit > 0){
            require(numberToMint + tokensMintedThisPeriod[msg.sender] <= currentMintLimit);
        }

        uint8 promoGene;

        if (currentPromoActive){
            promoGene = currentPromoGene;
        }

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

        for (uint i = 0; i < numberToMint; i++) {
            // Get new genes for the bitkoi but don't send in a promo gene
            uint256 newGenes = bitKoiTraits.smooshFish(0, 0, promoGene, block.number);
            
            _createBitKoi(0, 0, 0, newGenes, false, promoGene, msg.sender);
            
            gen0CreatedCount++;
            
            if (requireMintPass){
                tokensAllowed[msg.sender]--;
            }
            tokensMintedThisPeriod[msg.sender]++;
        }
        
        // update the most recently participated in mint event
        lastMintParticipated[msg.sender] = mintEventStarted;
        
    }

    /// @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 _sendTo the future owner of the created fish. Default to contract COO
    function createPromoFish(uint256 _genes, address _sendTo, bool _hatched, uint8 promoGene) external onlyCOO {

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

        require(promoCreatedCount < PROMO_CREATION_LIMIT);

        promoCreatedCount++;

        _createBitKoi(0, 0, 0, _genes, _hatched, promoGene, _sendTo);
    }

}

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, true, 0, address(msg.sender));

    }

    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 onlyCLevel {
        baseURI = _newBaseURI;
    }

    function setContractURI(string memory _newContractURI) public onlyCLevel {
        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();
    }

    function withdrawBalance() external onlyCFO {
        payable(cfoAddress).transfer(address(this).balance);
    }

    /// @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,
        uint64 spawnTime,
        uint64 hatchTime,
        uint256 parent1Id,
        uint256 parent2Id,
        uint256 generation,
        uint256 cooldownEndBlock,
        uint256 genes,
        uint8 promoGene
    ) {

        BitKoi storage fish = bitKoi[_id];

        isReady = (fish.cooldownEndBlock <= block.number);

        uint256 bitKoiGenes;

        if (fish.hatchTime > 0){
            bitKoiGenes = fish.genes;
        }

        cooldownIndex = uint256(fish.cooldownIndex);
        nextActionAt = uint256(fish.cooldownEndBlock);
        spawnTime = uint64(fish.spawnTime);
        hatchTime = uint64(fish.hatchTime);
        parent1Id = uint256(fish.parent1Id);
        parent2Id = uint256(fish.parent2Id);
        generation = uint256(fish.generation);
        cooldownEndBlock = uint256(fish.cooldownEndBlock);
        genes = bitKoiGenes;
        promoGene = uint8(fish.promoGene);
    }
}

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":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"fishId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"hatchTime","type":"uint64"}],"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":"uint256","name":"fishId","type":"uint256"},{"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":[],"name":"allowMinting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","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":[],"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":"_genes","type":"uint256"},{"internalType":"address","name":"_sendTo","type":"address"},{"internalType":"bool","name":"_hatched","type":"bool"},{"internalType":"uint8","name":"promoGene","type":"uint8"}],"name":"createPromoFish","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentGen0Cap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentMintLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPromoActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPromoGene","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"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":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getAvailablePasses","outputs":[{"internalType":"uint256","name":"","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":"uint64","name":"spawnTime","type":"uint64"},{"internalType":"uint64","name":"hatchTime","type":"uint64"},{"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"},{"internalType":"uint8","name":"promoGene","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","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":"_address","type":"address"}],"name":"getLastMintParticipated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getMintedThisPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"internalType":"uint256","name":"_fishId","type":"uint256"}],"name":"hatchBitKoi","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"hatchFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_koiId","type":"uint256"}],"name":"isReadyToBreed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintEventStarted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberToMint","type":"uint256"}],"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":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","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":[],"name":"requireMintPass","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"requiredHoldings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resetMintEventClock","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":"bool","name":"_val","type":"bool"}],"name":"setAllowMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_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":"_val","type":"uint256"}],"name":"setHolderRequirement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_val","type":"uint256"}],"name":"setMintLimitPerPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_val","type":"uint8"}],"name":"setPromoGene","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_status","type":"bool"}],"name":"setPromoStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_val","type":"bool"}],"name":"setRequireMintPasses","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":"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":[{"internalType":"address[]","name":"_addressList","type":"address[]"},{"internalType":"uint256","name":"numberOfPasses","type":"uint256"}],"name":"whitelistMintPasses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawBalance","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6002805460ff60a01b19169055600d805460ff191690556000601255610240604052603c6080908152607860a05261012c60c05261025860e05261070861010052610e1061012052611c2061014052613840610160526170806101805261e1006101a052620151806101c0526202a3006101e052620546006102005262093a80610220526200009390601390600e62000dd9565b50600f601555600060178190556018819055601c805461ffff19908116909155601d829055601e8281556064601f5542602090815560219390935560258054909216909155604080518082019091528181527f68747470733a2f2f7777772e6269746b6f692e636f2f6170692f6e66742f00009201918252620001199160269162000e7c565b506040805180820190915260158082527f68747470733a2f2f7777772e6269746b6f692e636f00000000000000000000006020909201918252620001609160279162000e7c565b503480156200016e57600080fd5b50604051620056ca380380620056ca833981016040819052620001919162000f10565b604051806040016040528060068152602001654269744b6f6960d01b815250604051806040016040528060068152602001654249544b4f4960d01b8152508282828160039080519060200190620001ea92919062000e7c565b5080516200020090600490602084019062000e7c565b5050506200021d62000217620002a060201b60201c565b620002bc565b601180546001600160a01b0319166001600160a01b03831617905562000243836200030e565b505060028054600080546001600160a01b03199081163390811783556001600160a81b03199093168317600160a01b179093556001805490931682178355620002989350918291829160001991839062000373565b5050620010c0565b6000620002b76200064f60201b620028e11760201c565b905090565b601080546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600d5460ff1615620003585760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b60448201526064015b60405180910390fd5b6200036381620006ae565b50600d805460ff19166001179055565b60008763ffffffff1688146200038857600080fd5b8663ffffffff1687146200039b57600080fd5b8561ffff168614620003ac57600080fd5b6000620003bb60028862001004565b9050600d8161ffff161115620003cf5750600d5b60008515620003db5750425b60006040518061012001604052808760ff168152602001426001600160401b03168152602001836001600160401b0316815260200160006001600160401b031681526020018c63ffffffff1681526020018b63ffffffff1681526020018461ffff1681526020018a61ffff16815260200189815250905060006016805490509050601682908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a8154816001600160401b0302191690836001600160401b0316021790555060408201518160000160096101000a8154816001600160401b0302191690836001600160401b0316021790555060608201518160000160116101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160000160196101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160006101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160046101000a81548161ffff021916908361ffff16021790555060e08201518160010160066101000a81548161ffff021916908361ffff160217905550610100820151816002015550508063ffffffff168114620005e457600080fd5b620005f0868262000750565b7fcbdde9319d4c5a92ce42b94fcce19f6419d9227af07758b008752acd4b5fa9cc818360200151604051620006389291909182526001600160401b0316602082015260400190565b60405180910390a19b9a5050505050505050505050565b600033301415620006a857600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b03169150620006ab9050565b50335b90565b6040518060800160405280604f81526020016200567b604f9139805160209182012082519282019290922060408051808201825260018152603160f81b90840152805180840194909452838101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608401523060808401524660a0808501919091528151808503909101815260c090930190528151910120600e55565b620007728282604051806020016040528060008152506200077660201b60201c565b5050565b620007828383620007ee565b62000791600084848462000944565b620007e95760405162461bcd60e51b815260206004820152603260248201526000805160206200565b83398151915260448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b60648201526084016200034f565b505050565b6001600160a01b038216620008465760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016200034f565b6000818152600560205260409020546001600160a01b031615620008ad5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016200034f565b620008bb6000838362000ab6565b6001600160a01b0382166000908152600660205260408120805460019290620008e690849062000fe9565b909155505060008181526005602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600062000965846001600160a01b031662000b9260201b6200293e1760201c565b1562000aaa576001600160a01b03841663150b7a0262000984620002a0565b8786866040518563ffffffff1660e01b8152600401620009a8949392919062000f6e565b602060405180830381600087803b158015620009c357600080fd5b505af1925050508015620009f6575060408051601f3d908101601f19168201909252620009f39181019062000f42565b60015b62000a8f573d80801562000a27576040519150601f19603f3d011682016040523d82523d6000602084013e62000a2c565b606091505b50805162000a875760405162461bcd60e51b815260206004820152603260248201526000805160206200565b83398151915260448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b60648201526084016200034f565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905062000aae565b5060015b949350505050565b62000ace838383620007e960201b620011c91760201c565b6001600160a01b03831662000b2c5762000b2681600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b62000b52565b816001600160a01b0316836001600160a01b03161462000b525762000b52838262000b98565b6001600160a01b03821662000b6c57620007e98162000c45565b826001600160a01b0316826001600160a01b031614620007e957620007e9828262000cff565b3b151590565b6000600162000bb28462000d5060201b62001a771760201c565b62000bbe919062001027565b6000838152600a602052604090205490915080821462000c12576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b5460009062000c599060019062001027565b6000838152600c6020526040812054600b805493945090928490811062000c845762000c84620010aa565b9060005260206000200154905080600b838154811062000ca85762000ca8620010aa565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b80548062000ce35762000ce362001094565b6001900381819060005260206000200160009055905550505050565b600062000d178362000d5060201b62001a771760201c565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b60006001600160a01b03821662000dbd5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b60648201526084016200034f565b506001600160a01b031660009081526006602052604090205490565b60028301918390821562000e6a5791602002820160005b8382111562000e3657835183826101000a81548163ffffffff021916908363ffffffff160217905550926020019260040160208160030104928301926001030262000df0565b801562000e685782816101000a81549063ffffffff021916905560040160208160030104928301926001030262000e36565b505b5062000e7892915062000ef9565b5090565b82805462000e8a9062001041565b90600052602060002090601f01602090048101928262000eae576000855562000e6a565b82601f1062000ec957805160ff191683800117855562000e6a565b8280016001018555821562000e6a579182015b8281111562000e6a57825182559160200191906001019062000edc565b5b8082111562000e78576000815560010162000efa565b60006020828403121562000f2357600080fd5b81516001600160a01b038116811462000f3b57600080fd5b9392505050565b60006020828403121562000f5557600080fd5b81516001600160e01b03198116811462000f3b57600080fd5b600060018060a01b038087168352602081871681850152856040850152608060608501528451915081608085015260005b8281101562000fbd5785810182015185820160a00152810162000f9f565b8281111562000fd057600060a084870101525b5050601f01601f19169190910160a00195945050505050565b6000821982111562000fff5762000fff6200107e565b500190565b6000826200102257634e487b7160e01b600052601260045260246000fd5b500490565b6000828210156200103c576200103c6200107e565b500390565b600181811c908216806200105657607f821691505b602082108114156200107857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b61458b80620010d06000396000f3fe60806040526004361061047e5760003560e01c80636352211e11610255578063b73aa20f11610144578063ddf4dcc8116100c1578063f137c84011610085578063f137c84014610da6578063f1c1395c14610db9578063f1ca941014610e3a578063f2fde38b14610e50578063fc537fd614610e70578063fd03082714610e8657600080fd5b8063ddf4dcc814610d05578063defb958414610d25578063e8a3d48514610d3b578063e985e9c514610d50578063eb4adf1d14610d7057600080fd5b8063d2e520fa11610108578063d2e520fa14610c7a578063d3e6f49f14610c9a578063d547cfb714610cba578063d71b3cee14610ccf578063dd02289214610ce557600080fd5b8063b73aa20f14610bc4578063b88d4fde14610be4578063bdd91cfc14610c04578063c320be0e14610c3a578063c87b56dd14610c5a57600080fd5b80638da5cb5b116101d2578063a22cb46511610196578063a22cb46514610b2e578063a40c3eab14610b4e578063b047fb5014610b64578063b325eb7014610b84578063b34cd6af14610ba457600080fd5b80638da5cb5b14610a86578063934fedf114610aa4578063938e3d7b14610ac457806395d89b4114610ae45780639d6fac6f14610af957600080fd5b8063724ed9ba11610219578063724ed9ba14610a055780637a7d493714610a1b5780638456cb5914610a315780638462151c14610a46578063850abb0b14610a7357600080fd5b80636352211e146109715780636868a45d146109915780637004fb84146109bd57806370a08231146109d0578063715018a6146109f057600080fd5b80631d94885c1161037157806342842e0e116102ee5780635663896e116102b25780635663896e146108f0578063596509eb146109105780635c975abb146109255780635dbd1f58146109465780635fd8c7101461095c57600080fd5b806342842e0e1461085057806346d22c70146108705780634e0a3379146108905780634f6ccce7146108b05780634f8c79f8146108d057600080fd5b80632d0335ab116103355780632d0335ab146107b25780632f745c59146107e857806330176e13146108085780633408e470146108285780633f4ba83a1461083b57600080fd5b80631d94885c1461071d57806320379ee51461073d57806323b872dd1461075257806327d7874c146107725780632ba73c151461079257600080fd5b8063095ea7b3116103ff5780631602a124116103c35780631602a1241461069957806317692b13146106b357806318160ddd146106d25780631817d87e146106e75780631bf698d3146106fd57600080fd5b8063095ea7b3146105e35780630a0f8168146106035780630c53c51c146106235780630f3b1a09146106365780630f7e59701461066c57600080fd5b80630519ce79116104465780630519ce791461053457806305e455461461056c57806306fdde031461058257806307611f80146105a4578063081812fc146105c357600080fd5b806301ffc9a714610483578063038d65da146104b85780630480329c146104dc57806304c4ef20146104fe57806304f1ceba14610514575b600080fd5b34801561048f57600080fd5b506104a361049e366004613fd5565b610ea6565b60405190151581526020015b60405180910390f35b3480156104c457600080fd5b506104ce601d5481565b6040519081526020016104af565b3480156104e857600080fd5b506104fc6104f7366004614074565b610ed1565b005b34801561050a57600080fd5b506104ce61af0081565b34801561052057600080fd5b506104fc61052f3660046140a6565b610f09565b34801561054057600080fd5b50600154610554906001600160a01b031681565b6040516001600160a01b0390911681526020016104af565b34801561057857600080fd5b506104ce601a5481565b34801561058e57600080fd5b50610597610f7a565b6040516104af919061428f565b3480156105b057600080fd5b50601c546104a390610100900460ff1681565b3480156105cf57600080fd5b506105546105de366004614074565b61100c565b3480156105ef57600080fd5b506104fc6105fe366004613ef5565b6110a6565b34801561060f57600080fd5b50600054610554906001600160a01b031681565b610597610631366004613e82565b6111ce565b34801561064257600080fd5b506104ce610651366004613d52565b6001600160a01b031660009081526022602052604090205490565b34801561067857600080fd5b50610597604051806040016040528060018152602001603160f81b81525081565b3480156106a557600080fd5b50601c546104a39060ff1681565b3480156106bf57600080fd5b506025546104a390610100900460ff1681565b3480156106de57600080fd5b50600b546104ce565b3480156106f357600080fd5b506104ce60175481565b34801561070957600080fd5b506104fc610718366004613f21565b6113b8565b34801561072957600080fd5b506104fc610738366004614074565b611453565b34801561074957600080fd5b50600e546104ce565b34801561075e57600080fd5b506104fc61076d366004613da8565b61146f565b34801561077e57600080fd5b506104fc61078d366004613d52565b6114a7565b34801561079e57600080fd5b506104fc6107ad366004613d52565b6114f3565b3480156107be57600080fd5b506104ce6107cd366004613d52565b6001600160a01b03166000908152600f602052604090205490565b3480156107f457600080fd5b506104ce610803366004613ef5565b61153f565b34801561081457600080fd5b506104fc61082336600461402c565b6115d5565b34801561083457600080fd5b50466104ce565b34801561084757600080fd5b506104fc61162d565b34801561085c57600080fd5b506104fc61086b366004613da8565b611679565b34801561087c57600080fd5b506104a361088b3660046140f7565b611694565b34801561089c57600080fd5b506104fc6108ab366004613d52565b61170e565b3480156108bc57600080fd5b506104ce6108cb366004614074565b61175a565b3480156108dc57600080fd5b506104fc6108eb366004614074565b6117ed565b3480156108fc57600080fd5b506104fc61090b366004614074565b611809565b34801561091c57600080fd5b506104fc611863565b34801561093157600080fd5b506002546104a390600160a01b900460ff1681565b34801561095257600080fd5b506104ce601f5481565b34801561096857600080fd5b506104fc6118aa565b34801561097d57600080fd5b5061055461098c366004614074565b6118fd565b34801561099d57600080fd5b506025546109ab9060ff1681565b60405160ff90911681526020016104af565b6104fc6109cb3660046140f7565b611974565b3480156109dc57600080fd5b506104ce6109eb366004613d52565b611a77565b3480156109fc57600080fd5b506104fc611afe565b348015610a1157600080fd5b506104ce60205481565b348015610a2757600080fd5b506104ce60155481565b348015610a3d57600080fd5b506104fc611b81565b348015610a5257600080fd5b50610a66610a61366004613d52565b611bee565b6040516104af919061424b565b6104fc610a81366004614074565b611cd0565b348015610a9257600080fd5b506010546001600160a01b0316610554565b348015610ab057600080fd5b506104fc610abf366004614074565b611e08565b348015610ad057600080fd5b506104fc610adf36600461402c565b611e24565b348015610af057600080fd5b50610597611e78565b348015610b0557600080fd5b50610b19610b14366004614074565b611e87565b60405163ffffffff90911681526020016104af565b348015610b3a57600080fd5b506104fc610b49366004613e54565b611eb7565b348015610b5a57600080fd5b506104ce60215481565b348015610b7057600080fd5b50600254610554906001600160a01b031681565b348015610b9057600080fd5b506104fc610b9f366004614074565b611fb9565b348015610bb057600080fd5b506104fc610bbf366004613f9b565b611fff565b348015610bd057600080fd5b506104fc610bdf366004614074565b612053565b348015610bf057600080fd5b506104fc610bff366004613de9565b61206f565b348015610c1057600080fd5b506104ce610c1f366004613d52565b6001600160a01b031660009081526023602052604090205490565b348015610c4657600080fd5b506104fc610c55366004614119565b6120a8565b348015610c6657600080fd5b50610597610c75366004614074565b6120ff565b348015610c8657600080fd5b506104fc610c95366004613f9b565b612139565b348015610ca657600080fd5b506104a3610cb5366004614074565b612194565b348015610cc657600080fd5b506105976121ec565b348015610cdb57600080fd5b506104ce601e5481565b348015610cf157600080fd5b506104fc610d00366004613d52565b6121fb565b348015610d1157600080fd5b506104fc610d20366004613f9b565b6122b4565b348015610d3157600080fd5b506104ce61145081565b348015610d4757600080fd5b506105976122e5565b348015610d5c57600080fd5b506104a3610d6b366004613d6f565b6122f4565b348015610d7c57600080fd5b506104ce610d8b366004613d52565b6001600160a01b031660009081526024602052604090205490565b6104fc610db4366004614074565b6123c4565b348015610dc557600080fd5b50610dd9610dd4366004614074565b612686565b604080519b15158c5260208c019a909a52988a01979097526001600160401b0395861660608a015294909316608088015260a087019190915260c086015260e085015261010084015261012083015260ff16610140820152610160016104af565b348015610e4657600080fd5b506104ce601b5481565b348015610e5c57600080fd5b506104fc610e6b366004613d52565b6127fa565b348015610e7c57600080fd5b506104ce60185481565b348015610e9257600080fd5b50601954610554906001600160a01b031681565b60006001600160e01b0319821663780e9d6360e01b1480610ecb5750610ecb82612944565b92915050565b6002546001600160a01b03163314610ee857600080fd5b61af0081601b54610ef99190614362565b1115610f0457600080fd5b601f55565b6002546001600160a01b03163314610f2057600080fd5b6001600160a01b038316610f3d576002546001600160a01b031692505b611450601a5410610f4d57600080fd5b601a8054906000610f5d8361443c565b9190505550610f73600080600087868689612994565b5050505050565b606060038054610f8990614407565b80601f0160208091040260200160405190810160405280929190818152602001828054610fb590614407565b80156110025780601f10610fd757610100808354040283529160200191611002565b820191906000526020600020905b815481529060010190602001808311610fe557829003601f168201915b5050505050905090565b6000818152600560205260408120546001600160a01b031661108a5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600760205260409020546001600160a01b031690565b60006110b1826118fd565b9050806001600160a01b0316836001600160a01b0316141561111f5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401611081565b806001600160a01b0316611131612c65565b6001600160a01b0316148061114d575061114d81610d6b612c65565b6111bf5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401611081565b6111c98383612c74565b505050565b60408051606081810183526001600160a01b0388166000818152600f60209081529085902054845283015291810186905261120c8782878787612ce2565b6112625760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401611081565b6001600160a01b0387166000908152600f6020526040902054611286906001612dd2565b6001600160a01b0388166000908152600f60205260409081902091909155517f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b906112d690899033908a906141e2565b60405180910390a1600080306001600160a01b0316888a6040516020016112fe92919061417c565b60408051601f198184030181529082905261131891614160565b6000604051808303816000865af19150503d8060008114611355576040519150601f19603f3d011682016040523d82523d6000602084013e61135a565b606091505b5091509150816113ac5760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401611081565b98975050505050505050565b6002546001600160a01b031633146113cf57600080fd5b60005b8281101561144d5781602260008686858181106113f1576113f16144ad565b90506020020160208101906114069190613d52565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546114359190614362565b909155508190506114458161443c565b9150506113d2565b50505050565b6002546001600160a01b0316331461146a57600080fd5b601e55565b61148061147a612c65565b82612dde565b61149c5760405162461bcd60e51b8152600401611081906142f4565b6111c9838383612ead565b6000546001600160a01b031633146114be57600080fd5b6001600160a01b0381166114d157600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461150a57600080fd5b6001600160a01b03811661151d57600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b600061154a83611a77565b82106115ac5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401611081565b506001600160a01b03919091166000908152600960209081526040808320938352929052205490565b6002546001600160a01b03163314806115f857506000546001600160a01b031633145b8061160d57506001546001600160a01b031633145b61161657600080fd5b8051611629906026906020840190613c0e565b5050565b6000546001600160a01b0316331461164457600080fd5b600254600160a01b900460ff1661165a57600080fd5b6019546001600160a01b031661166f57600080fd5b611677613058565b565b6111c98383836040518060200160405280600081525061206f565b60008083116116a257600080fd5b600082116116af57600080fd5b6000601684815481106116c4576116c46144ad565b906000526020600020906003020190506000601684815481106116e9576116e96144ad565b9060005260206000209060030201905061170582868387613094565b95945050505050565b6000546001600160a01b0316331461172557600080fd5b6001600160a01b03811661173857600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000611765600b5490565b82106117c85760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401611081565b600b82815481106117db576117db6144ad565b90600052602060002001549050919050565b6002546001600160a01b0316331461180457600080fd5b601855565b6002546001600160a01b031633148061182c57506000546001600160a01b031633145b8061184157506001546001600160a01b031633145b61184a57600080fd5b60135463ffffffff16811061185e57600080fd5b601555565b6002546001600160a01b031633148061188657506000546001600160a01b031633145b8061189b57506001546001600160a01b031633145b6118a457600080fd5b42602055565b6001546001600160a01b031633146118c157600080fd5b6001546040516001600160a01b03909116904780156108fc02916000818181858888f193505050501580156118fa573d6000803e3d6000fd5b50565b6000818152600560205260408120546001600160a01b031680610ecb5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401611081565b600254600160a01b900460ff161561198b57600080fd5b60175434101561199a57600080fd5b6119a4338361322d565b6119ad57600080fd5b6119b7338261322d565b6119c057600080fd5b6000601683815481106119d5576119d56144ad565b90600052602060002090600302019050611a0381546001600160401b03438116600160881b90920416111590565b611a0c57600080fd5b600060168381548110611a2157611a216144ad565b90600052602060002090600302019050611a4f81546001600160401b03438116600160881b90920416111590565b611a5857600080fd5b611a6482858386613094565b611a6d57600080fd5b610f738484613253565b60006001600160a01b038216611ae25760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401611081565b506001600160a01b031660009081526006602052604090205490565b611b06612c65565b6001600160a01b0316611b216010546001600160a01b031690565b6001600160a01b031614611b775760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611081565b611677600061340b565b6002546001600160a01b0316331480611ba457506000546001600160a01b031633145b80611bb957506001546001600160a01b031633145b611bc257600080fd5b600254600160a01b900460ff1615611bd957600080fd5b6002805460ff60a01b1916600160a01b179055565b60606000611bfb83611a77565b905080611c18575050604080516000815260208101909152919050565b6000816001600160401b03811115611c3257611c326144c3565b604051908082528060200260200182016040528015611c5b578160200160208202803683370190505b5090506000805b611c6d6001856143ad565b8111611cc0576000611c7f878361153f565b905080848481518110611c9457611c946144ad565b602090810291909101015282611ca98161443c565b935050508080611cb89061443c565b915050611c62565b5090949350505050565b50919050565b600254600160a01b900460ff1615611ce757600080fd5b601854341015611cf657600080fd5b611d00338261322d565b611d0957600080fd5b600060168281548110611d1e57611d1e6144ad565b600091825260209091206003909102018054909150600160481b90046001600160401b031615611d4d57600080fd5b80546001600160401b034216600160481b0270ffffffffffffffff000000000000000000199091161781556001546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015611db1573d6000803e3d6000fd5b5080546040805133815260208101859052600160481b9092046001600160401b0316908201527f4d29afe8e5fcaf220a83a773707c7593e76f0cd2b877752234ffdc8c68ece3529060600160405180910390a15050565b6002546001600160a01b03163314611e1f57600080fd5b601755565b6002546001600160a01b0316331480611e4757506000546001600160a01b031633145b80611e5c57506001546001600160a01b031633145b611e6557600080fd5b8051611629906027906020840190613c0e565b606060048054610f8990614407565b601381600e8110611e9757600080fd5b60089182820401919006600402915054906101000a900463ffffffff1681565b611ebf612c65565b6001600160a01b0316826001600160a01b03161415611f205760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401611081565b8060086000611f2d612c65565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155611f71612c65565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611fad911515815260200190565b60405180910390a35050565b6002546001600160a01b0316331480611fdc57506000546001600160a01b031633145b80611ff157506001546001600160a01b031633145b611ffa57600080fd5b601d55565b6002546001600160a01b031633148061202257506000546001600160a01b031633145b8061203757506001546001600160a01b031633145b61204057600080fd5b601c805460ff1916911515919091179055565b6002546001600160a01b0316331461206a57600080fd5b602155565b61208061207a612c65565b83612dde565b61209c5760405162461bcd60e51b8152600401611081906142f4565b61144d8484848461345d565b6002546001600160a01b03163314806120cb57506000546001600160a01b031633145b806120e057506001546001600160a01b031633145b6120e957600080fd5b6025805460ff191660ff92909216919091179055565b60606121096121ec565b61211283613490565b6040516020016121239291906141b3565b6040516020818303038152906040529050919050565b6002546001600160a01b031633148061215c57506000546001600160a01b031633145b8061217157506001546001600160a01b031633145b61217a57600080fd5b602580549115156101000261ff0019909216919091179055565b60008082116121a257600080fd5b6000601683815481106121b7576121b76144ad565b906000526020600020906003020190506121e581546001600160401b03438116600160881b90920416111590565b9392505050565b606060268054610f8990614407565b6000546001600160a01b0316331461221257600080fd5b6000819050806001600160a01b031663f4bd77d76040518163ffffffff1660e01b815260040160206040518083038186803b15801561225057600080fd5b505afa158015612264573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122889190613fb8565b61229157600080fd5b601980546001600160a01b0319166001600160a01b039290921691909117905550565b6002546001600160a01b031633146122cb57600080fd5b601c80549115156101000261ff0019909216919091179055565b606060278054610f8990614407565b60115460405163c455279160e01b81526001600160a01b03848116600483015260009281169190841690829063c45527919060240160206040518083038186803b15801561234157600080fd5b505afa158015612355573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612379919061400f565b6001600160a01b03161415612392576001915050610ecb565b6001600160a01b0380851660009081526008602090815260408083209387168352929052205460ff165b949350505050565b600254600160a01b900460ff16156123db57600080fd5b601c5460ff166123ea57600080fd5b600081116123f757600080fd5b80601e54612405919061438e565b34101561241157600080fd5b601f5481601b546124229190614362565b111561242d57600080fd5b61af0081601b5461243e9190614362565b111561244957600080fd5b601d5461245533611a77565b101561246057600080fd5b601c54610100900460ff161561248c573360009081526022602052604090205481111561248c57600080fd5b60208054336000908152602390925260409091205410156124b857336000908152602460205260408120555b602154156124e857602154336000908152602460205260409020546124dd9083614362565b11156124e857600080fd5b602554600090610100900460ff1615612503575060255460ff165b6001546040516001600160a01b03909116903480156108fc02916000818181858888f1935050505015801561253c573d6000803e3d6000fd5b5060005b8281101561266c57601954604051631381ebf360e31b81526000600482018190526024820181905260ff85166044830152436064830152916001600160a01b031690639c0f5f9890608401602060405180830381600087803b1580156125a557600080fd5b505af11580156125b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125dd919061408d565b90506125f160008060008460008833612994565b50601b80549060006126028361443c565b9091555050601c54610100900460ff161561263857336000908152602260205260408120805491612632836143f0565b91905055505b3360009081526024602052604081208054916126538361443c565b91905055505080806126649061443c565b915050612540565b505060208054336000908152602390925260409091205550565b60008060008060008060008060008060008060168d815481106126ab576126ab6144ad565b6000918252602082206003909102018054436001600160401b03600160881b8304811691909111159f50919350600160481b900416156126ec575060028101545b8160010160049054906101000a900461ffff1661ffff169b508160000160119054906101000a90046001600160401b03166001600160401b03169a508160000160019054906101000a90046001600160401b031699508160000160099054906101000a90046001600160401b031698508160000160199054906101000a900463ffffffff1663ffffffff1697508160010160009054906101000a900463ffffffff1663ffffffff1696508160010160069054906101000a900461ffff1661ffff1695508160000160119054906101000a90046001600160401b03166001600160401b031694508093508160000160009054906101000a900460ff169250505091939597999b90929496989a50565b612802612c65565b6001600160a01b031661281d6010546001600160a01b031690565b6001600160a01b0316146128735760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611081565b6001600160a01b0381166128d85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401611081565b6118fa8161340b565b60003330141561293857600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b0316915061293b9050565b50335b90565b3b151590565b60006001600160e01b031982166380ac58cd60e01b148061297557506001600160e01b03198216635b5e139f60e01b145b80610ecb57506301ffc9a760e01b6001600160e01b0319831614610ecb565b60008763ffffffff1688146129a857600080fd5b8663ffffffff1687146129ba57600080fd5b8561ffff1686146129ca57600080fd5b60006129d760028861437a565b9050600d8161ffff1611156129ea5750600d5b600085156129f55750425b60006040518061012001604052808760ff168152602001426001600160401b03168152602001836001600160401b0316815260200160006001600160401b031681526020018c63ffffffff1681526020018b63ffffffff1681526020018461ffff1681526020018a61ffff16815260200189815250905060006016805490509050601682908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a8154816001600160401b0302191690836001600160401b0316021790555060408201518160000160096101000a8154816001600160401b0302191690836001600160401b0316021790555060608201518160000160116101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160000160196101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160006101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160046101000a81548161ffff021916908361ffff16021790555060e08201518160010160066101000a81548161ffff021916908361ffff160217905550610100820151816002015550508063ffffffff168114612bfd57600080fd5b612c07868261358d565b7fcbdde9319d4c5a92ce42b94fcce19f6419d9227af07758b008752acd4b5fa9cc818360200151604051612c4e9291909182526001600160401b0316602082015260400190565b60405180910390a19b9a5050505050505050505050565b6000612c6f6128e1565b905090565b600081815260076020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612ca9826118fd565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006001600160a01b038616612d485760405162461bcd60e51b815260206004820152602560248201527f4e61746976654d6574615472616e73616374696f6e3a20494e56414c49445f5360448201526424a3a722a960d91b6064820152608401611081565b6001612d5b612d56876135a7565b613624565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa158015612da9573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b031614905095945050505050565b60006121e58284614362565b6000818152600560205260408120546001600160a01b0316612e575760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401611081565b6000612e62836118fd565b9050806001600160a01b0316846001600160a01b03161480612e9d5750836001600160a01b0316612e928461100c565b6001600160a01b0316145b806123bc57506123bc81856122f4565b826001600160a01b0316612ec0826118fd565b6001600160a01b031614612f285760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401611081565b6001600160a01b038216612f8a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401611081565b612f95838383613654565b612fa0600082612c74565b6001600160a01b0383166000908152600660205260408120805460019290612fc99084906143ad565b90915550506001600160a01b0382166000908152600660205260408120805460019290612ff7908490614362565b909155505060008181526005602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000546001600160a01b0316331461306f57600080fd5b600254600160a01b900460ff1661308557600080fd5b6002805460ff60a01b19169055565b6000818414156130a6575060006123bc565b600285015415806130b957506002830154155b156130c6575060006123bc565b8454600160481b90046001600160401b031615806130f357508254600160481b90046001600160401b0316155b15613100575060006123bc565b8454600160c81b900463ffffffff168214806131255750600185015463ffffffff1682145b15613132575060006123bc565b8254600160c81b900463ffffffff168414806131575750600183015463ffffffff1684145b15613164575060006123bc565b8254600160c81b900463ffffffff16158061318b57508454600160c81b900463ffffffff16155b15613198575060016123bc565b84548354600160c81b9182900463ffffffff908116929091041614806131d3575060018501548354600160c81b900463ffffffff9081169116145b156131e0575060006123bc565b8454600184015463ffffffff908116600160c81b90920416148061321557506001808601549084015463ffffffff9081169116145b15613222575060006123bc565b506001949350505050565b6000826001600160a01b0316613242836118fd565b6001600160a01b0316149392505050565b60008060168481548110613269576132696144ad565b9060005260206000209060030201905060006016848154811061328e5761328e6144ad565b6000918252602090912060018085015460039093029091019081015490925061ffff660100000000000092839004811692909104168110156132df575060018101546601000000000000900461ffff165b6001546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015613318573d6000803e3d6000fd5b50601954600284810154908401548554604051631381ebf360e31b815260048101939093526024830191909152600060448301819052600160881b9091046001600160401b03166064830152916001600160a01b031690639c0f5f9890608401602060405180830381600087803b15801561339257600080fd5b505af11580156133a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ca919061408d565b905060006133ec88886133de866001614345565b61ffff168560008033612994565b90506133f78561370c565b6134008461370c565b979650505050505050565b601080546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b613468848484612ead565b613474848484846137ec565b61144d5760405162461bcd60e51b8152600401611081906142a2565b6060816134b45750506040805180820190915260018152600360fc1b602082015290565b8160005b81156134de57806134c88161443c565b91506134d79050600a8361437a565b91506134b8565b6000816001600160401b038111156134f8576134f86144c3565b6040519080825280601f01601f191660200182016040528015613522576020820181803683370190505b5090505b84156123bc576135376001836143ad565b9150613544600a86614457565b61354f906030614362565b60f81b818381518110613564576135646144ad565b60200101906001600160f81b031916908160001a905350613586600a8661437a565b9450613526565b6116298282604051806020016040528060008152506138fd565b60006040518060800160405280604381526020016145136043913980516020918201208351848301516040808701518051908601209051613607950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061362f600e5490565b60405161190160f01b6020820152602281019190915260428101839052606201613607565b6001600160a01b0383166136af576136aa81600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b6136d2565b816001600160a01b0316836001600160a01b0316146136d2576136d28382613930565b6001600160a01b0382166136e9576111c9816139cd565b826001600160a01b0316826001600160a01b0316146111c9576111c98282613a7c565b6015546001820154439190601390640100000000900461ffff16600e8110613736576137366144ad565b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16613762919061437a565b61376c9190614362565b815467ffffffffffffffff60881b1916600160881b6001600160401b0392909216919091021781556001810154600d64010000000090910461ffff1610156118fa57600181810180546004906137cf908490640100000000900461ffff16614345565b92506101000a81548161ffff021916908361ffff16021790555050565b60006001600160a01b0384163b156138f557836001600160a01b031663150b7a02613815612c65565b8786866040518563ffffffff1660e01b8152600401613837949392919061420e565b602060405180830381600087803b15801561385157600080fd5b505af1925050508015613881575060408051601f3d908101601f1916820190925261387e91810190613ff2565b60015b6138db573d8080156138af576040519150601f19603f3d011682016040523d82523d6000602084013e6138b4565b606091505b5080516138d35760405162461bcd60e51b8152600401611081906142a2565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506123bc565b5060016123bc565b6139078383613ac0565b61391460008484846137ec565b6111c95760405162461bcd60e51b8152600401611081906142a2565b6000600161393d84611a77565b61394791906143ad565b6000838152600a602052604090205490915080821461399a576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b546000906139df906001906143ad565b6000838152600c6020526040812054600b8054939450909284908110613a0757613a076144ad565b9060005260206000200154905080600b8381548110613a2857613a286144ad565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b805480613a6057613a60614497565b6001900381819060005260206000200160009055905550505050565b6000613a8783611a77565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b6001600160a01b038216613b165760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401611081565b6000818152600560205260409020546001600160a01b031615613b7b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401611081565b613b8760008383613654565b6001600160a01b0382166000908152600660205260408120805460019290613bb0908490614362565b909155505060008181526005602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054613c1a90614407565b90600052602060002090601f016020900481019282613c3c5760008555613c82565b82601f10613c5557805160ff1916838001178555613c82565b82800160010185558215613c82579182015b82811115613c82578251825591602001919060010190613c67565b50613c8e929150613c92565b5090565b5b80821115613c8e5760008155600101613c93565b60006001600160401b0380841115613cc157613cc16144c3565b604051601f8501601f19908116603f01168101908282118183101715613ce957613ce96144c3565b81604052809350858152868686011115613d0257600080fd5b858560208301376000602087830101525050509392505050565b600082601f830112613d2d57600080fd5b6121e583833560208501613ca7565b803560ff81168114613d4d57600080fd5b919050565b600060208284031215613d6457600080fd5b81356121e5816144d9565b60008060408385031215613d8257600080fd5b8235613d8d816144d9565b91506020830135613d9d816144d9565b809150509250929050565b600080600060608486031215613dbd57600080fd5b8335613dc8816144d9565b92506020840135613dd8816144d9565b929592945050506040919091013590565b60008060008060808587031215613dff57600080fd5b8435613e0a816144d9565b93506020850135613e1a816144d9565b92506040850135915060608501356001600160401b03811115613e3c57600080fd5b613e4887828801613d1c565b91505092959194509250565b60008060408385031215613e6757600080fd5b8235613e72816144d9565b91506020830135613d9d816144ee565b600080600080600060a08688031215613e9a57600080fd5b8535613ea5816144d9565b945060208601356001600160401b03811115613ec057600080fd5b613ecc88828901613d1c565b9450506040860135925060608601359150613ee960808701613d3c565b90509295509295909350565b60008060408385031215613f0857600080fd5b8235613f13816144d9565b946020939093013593505050565b600080600060408486031215613f3657600080fd5b83356001600160401b0380821115613f4d57600080fd5b818601915086601f830112613f6157600080fd5b813581811115613f7057600080fd5b8760208260051b8501011115613f8557600080fd5b6020928301989097509590910135949350505050565b600060208284031215613fad57600080fd5b81356121e5816144ee565b600060208284031215613fca57600080fd5b81516121e5816144ee565b600060208284031215613fe757600080fd5b81356121e5816144fc565b60006020828403121561400457600080fd5b81516121e5816144fc565b60006020828403121561402157600080fd5b81516121e5816144d9565b60006020828403121561403e57600080fd5b81356001600160401b0381111561405457600080fd5b8201601f8101841361406557600080fd5b6123bc84823560208401613ca7565b60006020828403121561408657600080fd5b5035919050565b60006020828403121561409f57600080fd5b5051919050565b600080600080608085870312156140bc57600080fd5b8435935060208501356140ce816144d9565b925060408501356140de816144ee565b91506140ec60608601613d3c565b905092959194509250565b6000806040838503121561410a57600080fd5b50508035926020909101359150565b60006020828403121561412b57600080fd5b6121e582613d3c565b6000815180845261414c8160208601602086016143c4565b601f01601f19169290920160200192915050565b600082516141728184602087016143c4565b9190910192915050565b6000835161418e8184602088016143c4565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b600083516141c58184602088016143c4565b8351908301906141d98183602088016143c4565b01949350505050565b6001600160a01b0384811682528316602082015260606040820181905260009061170590830184614134565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061424190830184614134565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561428357835183529284019291840191600101614267565b50909695505050505050565b6020815260006121e56020830184614134565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b600061ffff8083168185168083038211156141d9576141d961446b565b600082198211156143755761437561446b565b500190565b60008261438957614389614481565b500490565b60008160001904831182151516156143a8576143a861446b565b500290565b6000828210156143bf576143bf61446b565b500390565b60005b838110156143df5781810151838201526020016143c7565b8381111561144d5750506000910152565b6000816143ff576143ff61446b565b506000190190565b600181811c9082168061441b57607f821691505b60208210811415611cca57634e487b7160e01b600052602260045260246000fd5b60006000198214156144505761445061446b565b5060010190565b60008261446657614466614481565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146118fa57600080fd5b80151581146118fa57600080fd5b6001600160e01b0319811681146118fa57600080fdfe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529a2646970667358221220516b3a64985c71ab5d00d69b85886eac17d225e5e77de1199fd2e96eee460ac464736f6c634300080700334552433732313a207472616e7366657220746f206e6f6e204552433732315265454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c6164647265737320766572696679696e67436f6e74726163742c627974657333322073616c7429000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1

Deployed Bytecode

0x60806040526004361061047e5760003560e01c80636352211e11610255578063b73aa20f11610144578063ddf4dcc8116100c1578063f137c84011610085578063f137c84014610da6578063f1c1395c14610db9578063f1ca941014610e3a578063f2fde38b14610e50578063fc537fd614610e70578063fd03082714610e8657600080fd5b8063ddf4dcc814610d05578063defb958414610d25578063e8a3d48514610d3b578063e985e9c514610d50578063eb4adf1d14610d7057600080fd5b8063d2e520fa11610108578063d2e520fa14610c7a578063d3e6f49f14610c9a578063d547cfb714610cba578063d71b3cee14610ccf578063dd02289214610ce557600080fd5b8063b73aa20f14610bc4578063b88d4fde14610be4578063bdd91cfc14610c04578063c320be0e14610c3a578063c87b56dd14610c5a57600080fd5b80638da5cb5b116101d2578063a22cb46511610196578063a22cb46514610b2e578063a40c3eab14610b4e578063b047fb5014610b64578063b325eb7014610b84578063b34cd6af14610ba457600080fd5b80638da5cb5b14610a86578063934fedf114610aa4578063938e3d7b14610ac457806395d89b4114610ae45780639d6fac6f14610af957600080fd5b8063724ed9ba11610219578063724ed9ba14610a055780637a7d493714610a1b5780638456cb5914610a315780638462151c14610a46578063850abb0b14610a7357600080fd5b80636352211e146109715780636868a45d146109915780637004fb84146109bd57806370a08231146109d0578063715018a6146109f057600080fd5b80631d94885c1161037157806342842e0e116102ee5780635663896e116102b25780635663896e146108f0578063596509eb146109105780635c975abb146109255780635dbd1f58146109465780635fd8c7101461095c57600080fd5b806342842e0e1461085057806346d22c70146108705780634e0a3379146108905780634f6ccce7146108b05780634f8c79f8146108d057600080fd5b80632d0335ab116103355780632d0335ab146107b25780632f745c59146107e857806330176e13146108085780633408e470146108285780633f4ba83a1461083b57600080fd5b80631d94885c1461071d57806320379ee51461073d57806323b872dd1461075257806327d7874c146107725780632ba73c151461079257600080fd5b8063095ea7b3116103ff5780631602a124116103c35780631602a1241461069957806317692b13146106b357806318160ddd146106d25780631817d87e146106e75780631bf698d3146106fd57600080fd5b8063095ea7b3146105e35780630a0f8168146106035780630c53c51c146106235780630f3b1a09146106365780630f7e59701461066c57600080fd5b80630519ce79116104465780630519ce791461053457806305e455461461056c57806306fdde031461058257806307611f80146105a4578063081812fc146105c357600080fd5b806301ffc9a714610483578063038d65da146104b85780630480329c146104dc57806304c4ef20146104fe57806304f1ceba14610514575b600080fd5b34801561048f57600080fd5b506104a361049e366004613fd5565b610ea6565b60405190151581526020015b60405180910390f35b3480156104c457600080fd5b506104ce601d5481565b6040519081526020016104af565b3480156104e857600080fd5b506104fc6104f7366004614074565b610ed1565b005b34801561050a57600080fd5b506104ce61af0081565b34801561052057600080fd5b506104fc61052f3660046140a6565b610f09565b34801561054057600080fd5b50600154610554906001600160a01b031681565b6040516001600160a01b0390911681526020016104af565b34801561057857600080fd5b506104ce601a5481565b34801561058e57600080fd5b50610597610f7a565b6040516104af919061428f565b3480156105b057600080fd5b50601c546104a390610100900460ff1681565b3480156105cf57600080fd5b506105546105de366004614074565b61100c565b3480156105ef57600080fd5b506104fc6105fe366004613ef5565b6110a6565b34801561060f57600080fd5b50600054610554906001600160a01b031681565b610597610631366004613e82565b6111ce565b34801561064257600080fd5b506104ce610651366004613d52565b6001600160a01b031660009081526022602052604090205490565b34801561067857600080fd5b50610597604051806040016040528060018152602001603160f81b81525081565b3480156106a557600080fd5b50601c546104a39060ff1681565b3480156106bf57600080fd5b506025546104a390610100900460ff1681565b3480156106de57600080fd5b50600b546104ce565b3480156106f357600080fd5b506104ce60175481565b34801561070957600080fd5b506104fc610718366004613f21565b6113b8565b34801561072957600080fd5b506104fc610738366004614074565b611453565b34801561074957600080fd5b50600e546104ce565b34801561075e57600080fd5b506104fc61076d366004613da8565b61146f565b34801561077e57600080fd5b506104fc61078d366004613d52565b6114a7565b34801561079e57600080fd5b506104fc6107ad366004613d52565b6114f3565b3480156107be57600080fd5b506104ce6107cd366004613d52565b6001600160a01b03166000908152600f602052604090205490565b3480156107f457600080fd5b506104ce610803366004613ef5565b61153f565b34801561081457600080fd5b506104fc61082336600461402c565b6115d5565b34801561083457600080fd5b50466104ce565b34801561084757600080fd5b506104fc61162d565b34801561085c57600080fd5b506104fc61086b366004613da8565b611679565b34801561087c57600080fd5b506104a361088b3660046140f7565b611694565b34801561089c57600080fd5b506104fc6108ab366004613d52565b61170e565b3480156108bc57600080fd5b506104ce6108cb366004614074565b61175a565b3480156108dc57600080fd5b506104fc6108eb366004614074565b6117ed565b3480156108fc57600080fd5b506104fc61090b366004614074565b611809565b34801561091c57600080fd5b506104fc611863565b34801561093157600080fd5b506002546104a390600160a01b900460ff1681565b34801561095257600080fd5b506104ce601f5481565b34801561096857600080fd5b506104fc6118aa565b34801561097d57600080fd5b5061055461098c366004614074565b6118fd565b34801561099d57600080fd5b506025546109ab9060ff1681565b60405160ff90911681526020016104af565b6104fc6109cb3660046140f7565b611974565b3480156109dc57600080fd5b506104ce6109eb366004613d52565b611a77565b3480156109fc57600080fd5b506104fc611afe565b348015610a1157600080fd5b506104ce60205481565b348015610a2757600080fd5b506104ce60155481565b348015610a3d57600080fd5b506104fc611b81565b348015610a5257600080fd5b50610a66610a61366004613d52565b611bee565b6040516104af919061424b565b6104fc610a81366004614074565b611cd0565b348015610a9257600080fd5b506010546001600160a01b0316610554565b348015610ab057600080fd5b506104fc610abf366004614074565b611e08565b348015610ad057600080fd5b506104fc610adf36600461402c565b611e24565b348015610af057600080fd5b50610597611e78565b348015610b0557600080fd5b50610b19610b14366004614074565b611e87565b60405163ffffffff90911681526020016104af565b348015610b3a57600080fd5b506104fc610b49366004613e54565b611eb7565b348015610b5a57600080fd5b506104ce60215481565b348015610b7057600080fd5b50600254610554906001600160a01b031681565b348015610b9057600080fd5b506104fc610b9f366004614074565b611fb9565b348015610bb057600080fd5b506104fc610bbf366004613f9b565b611fff565b348015610bd057600080fd5b506104fc610bdf366004614074565b612053565b348015610bf057600080fd5b506104fc610bff366004613de9565b61206f565b348015610c1057600080fd5b506104ce610c1f366004613d52565b6001600160a01b031660009081526023602052604090205490565b348015610c4657600080fd5b506104fc610c55366004614119565b6120a8565b348015610c6657600080fd5b50610597610c75366004614074565b6120ff565b348015610c8657600080fd5b506104fc610c95366004613f9b565b612139565b348015610ca657600080fd5b506104a3610cb5366004614074565b612194565b348015610cc657600080fd5b506105976121ec565b348015610cdb57600080fd5b506104ce601e5481565b348015610cf157600080fd5b506104fc610d00366004613d52565b6121fb565b348015610d1157600080fd5b506104fc610d20366004613f9b565b6122b4565b348015610d3157600080fd5b506104ce61145081565b348015610d4757600080fd5b506105976122e5565b348015610d5c57600080fd5b506104a3610d6b366004613d6f565b6122f4565b348015610d7c57600080fd5b506104ce610d8b366004613d52565b6001600160a01b031660009081526024602052604090205490565b6104fc610db4366004614074565b6123c4565b348015610dc557600080fd5b50610dd9610dd4366004614074565b612686565b604080519b15158c5260208c019a909a52988a01979097526001600160401b0395861660608a015294909316608088015260a087019190915260c086015260e085015261010084015261012083015260ff16610140820152610160016104af565b348015610e4657600080fd5b506104ce601b5481565b348015610e5c57600080fd5b506104fc610e6b366004613d52565b6127fa565b348015610e7c57600080fd5b506104ce60185481565b348015610e9257600080fd5b50601954610554906001600160a01b031681565b60006001600160e01b0319821663780e9d6360e01b1480610ecb5750610ecb82612944565b92915050565b6002546001600160a01b03163314610ee857600080fd5b61af0081601b54610ef99190614362565b1115610f0457600080fd5b601f55565b6002546001600160a01b03163314610f2057600080fd5b6001600160a01b038316610f3d576002546001600160a01b031692505b611450601a5410610f4d57600080fd5b601a8054906000610f5d8361443c565b9190505550610f73600080600087868689612994565b5050505050565b606060038054610f8990614407565b80601f0160208091040260200160405190810160405280929190818152602001828054610fb590614407565b80156110025780601f10610fd757610100808354040283529160200191611002565b820191906000526020600020905b815481529060010190602001808311610fe557829003601f168201915b5050505050905090565b6000818152600560205260408120546001600160a01b031661108a5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600760205260409020546001600160a01b031690565b60006110b1826118fd565b9050806001600160a01b0316836001600160a01b0316141561111f5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401611081565b806001600160a01b0316611131612c65565b6001600160a01b0316148061114d575061114d81610d6b612c65565b6111bf5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401611081565b6111c98383612c74565b505050565b60408051606081810183526001600160a01b0388166000818152600f60209081529085902054845283015291810186905261120c8782878787612ce2565b6112625760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401611081565b6001600160a01b0387166000908152600f6020526040902054611286906001612dd2565b6001600160a01b0388166000908152600f60205260409081902091909155517f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b906112d690899033908a906141e2565b60405180910390a1600080306001600160a01b0316888a6040516020016112fe92919061417c565b60408051601f198184030181529082905261131891614160565b6000604051808303816000865af19150503d8060008114611355576040519150601f19603f3d011682016040523d82523d6000602084013e61135a565b606091505b5091509150816113ac5760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401611081565b98975050505050505050565b6002546001600160a01b031633146113cf57600080fd5b60005b8281101561144d5781602260008686858181106113f1576113f16144ad565b90506020020160208101906114069190613d52565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546114359190614362565b909155508190506114458161443c565b9150506113d2565b50505050565b6002546001600160a01b0316331461146a57600080fd5b601e55565b61148061147a612c65565b82612dde565b61149c5760405162461bcd60e51b8152600401611081906142f4565b6111c9838383612ead565b6000546001600160a01b031633146114be57600080fd5b6001600160a01b0381166114d157600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461150a57600080fd5b6001600160a01b03811661151d57600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b600061154a83611a77565b82106115ac5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401611081565b506001600160a01b03919091166000908152600960209081526040808320938352929052205490565b6002546001600160a01b03163314806115f857506000546001600160a01b031633145b8061160d57506001546001600160a01b031633145b61161657600080fd5b8051611629906026906020840190613c0e565b5050565b6000546001600160a01b0316331461164457600080fd5b600254600160a01b900460ff1661165a57600080fd5b6019546001600160a01b031661166f57600080fd5b611677613058565b565b6111c98383836040518060200160405280600081525061206f565b60008083116116a257600080fd5b600082116116af57600080fd5b6000601684815481106116c4576116c46144ad565b906000526020600020906003020190506000601684815481106116e9576116e96144ad565b9060005260206000209060030201905061170582868387613094565b95945050505050565b6000546001600160a01b0316331461172557600080fd5b6001600160a01b03811661173857600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000611765600b5490565b82106117c85760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401611081565b600b82815481106117db576117db6144ad565b90600052602060002001549050919050565b6002546001600160a01b0316331461180457600080fd5b601855565b6002546001600160a01b031633148061182c57506000546001600160a01b031633145b8061184157506001546001600160a01b031633145b61184a57600080fd5b60135463ffffffff16811061185e57600080fd5b601555565b6002546001600160a01b031633148061188657506000546001600160a01b031633145b8061189b57506001546001600160a01b031633145b6118a457600080fd5b42602055565b6001546001600160a01b031633146118c157600080fd5b6001546040516001600160a01b03909116904780156108fc02916000818181858888f193505050501580156118fa573d6000803e3d6000fd5b50565b6000818152600560205260408120546001600160a01b031680610ecb5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401611081565b600254600160a01b900460ff161561198b57600080fd5b60175434101561199a57600080fd5b6119a4338361322d565b6119ad57600080fd5b6119b7338261322d565b6119c057600080fd5b6000601683815481106119d5576119d56144ad565b90600052602060002090600302019050611a0381546001600160401b03438116600160881b90920416111590565b611a0c57600080fd5b600060168381548110611a2157611a216144ad565b90600052602060002090600302019050611a4f81546001600160401b03438116600160881b90920416111590565b611a5857600080fd5b611a6482858386613094565b611a6d57600080fd5b610f738484613253565b60006001600160a01b038216611ae25760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401611081565b506001600160a01b031660009081526006602052604090205490565b611b06612c65565b6001600160a01b0316611b216010546001600160a01b031690565b6001600160a01b031614611b775760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611081565b611677600061340b565b6002546001600160a01b0316331480611ba457506000546001600160a01b031633145b80611bb957506001546001600160a01b031633145b611bc257600080fd5b600254600160a01b900460ff1615611bd957600080fd5b6002805460ff60a01b1916600160a01b179055565b60606000611bfb83611a77565b905080611c18575050604080516000815260208101909152919050565b6000816001600160401b03811115611c3257611c326144c3565b604051908082528060200260200182016040528015611c5b578160200160208202803683370190505b5090506000805b611c6d6001856143ad565b8111611cc0576000611c7f878361153f565b905080848481518110611c9457611c946144ad565b602090810291909101015282611ca98161443c565b935050508080611cb89061443c565b915050611c62565b5090949350505050565b50919050565b600254600160a01b900460ff1615611ce757600080fd5b601854341015611cf657600080fd5b611d00338261322d565b611d0957600080fd5b600060168281548110611d1e57611d1e6144ad565b600091825260209091206003909102018054909150600160481b90046001600160401b031615611d4d57600080fd5b80546001600160401b034216600160481b0270ffffffffffffffff000000000000000000199091161781556001546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015611db1573d6000803e3d6000fd5b5080546040805133815260208101859052600160481b9092046001600160401b0316908201527f4d29afe8e5fcaf220a83a773707c7593e76f0cd2b877752234ffdc8c68ece3529060600160405180910390a15050565b6002546001600160a01b03163314611e1f57600080fd5b601755565b6002546001600160a01b0316331480611e4757506000546001600160a01b031633145b80611e5c57506001546001600160a01b031633145b611e6557600080fd5b8051611629906027906020840190613c0e565b606060048054610f8990614407565b601381600e8110611e9757600080fd5b60089182820401919006600402915054906101000a900463ffffffff1681565b611ebf612c65565b6001600160a01b0316826001600160a01b03161415611f205760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401611081565b8060086000611f2d612c65565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155611f71612c65565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611fad911515815260200190565b60405180910390a35050565b6002546001600160a01b0316331480611fdc57506000546001600160a01b031633145b80611ff157506001546001600160a01b031633145b611ffa57600080fd5b601d55565b6002546001600160a01b031633148061202257506000546001600160a01b031633145b8061203757506001546001600160a01b031633145b61204057600080fd5b601c805460ff1916911515919091179055565b6002546001600160a01b0316331461206a57600080fd5b602155565b61208061207a612c65565b83612dde565b61209c5760405162461bcd60e51b8152600401611081906142f4565b61144d8484848461345d565b6002546001600160a01b03163314806120cb57506000546001600160a01b031633145b806120e057506001546001600160a01b031633145b6120e957600080fd5b6025805460ff191660ff92909216919091179055565b60606121096121ec565b61211283613490565b6040516020016121239291906141b3565b6040516020818303038152906040529050919050565b6002546001600160a01b031633148061215c57506000546001600160a01b031633145b8061217157506001546001600160a01b031633145b61217a57600080fd5b602580549115156101000261ff0019909216919091179055565b60008082116121a257600080fd5b6000601683815481106121b7576121b76144ad565b906000526020600020906003020190506121e581546001600160401b03438116600160881b90920416111590565b9392505050565b606060268054610f8990614407565b6000546001600160a01b0316331461221257600080fd5b6000819050806001600160a01b031663f4bd77d76040518163ffffffff1660e01b815260040160206040518083038186803b15801561225057600080fd5b505afa158015612264573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122889190613fb8565b61229157600080fd5b601980546001600160a01b0319166001600160a01b039290921691909117905550565b6002546001600160a01b031633146122cb57600080fd5b601c80549115156101000261ff0019909216919091179055565b606060278054610f8990614407565b60115460405163c455279160e01b81526001600160a01b03848116600483015260009281169190841690829063c45527919060240160206040518083038186803b15801561234157600080fd5b505afa158015612355573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612379919061400f565b6001600160a01b03161415612392576001915050610ecb565b6001600160a01b0380851660009081526008602090815260408083209387168352929052205460ff165b949350505050565b600254600160a01b900460ff16156123db57600080fd5b601c5460ff166123ea57600080fd5b600081116123f757600080fd5b80601e54612405919061438e565b34101561241157600080fd5b601f5481601b546124229190614362565b111561242d57600080fd5b61af0081601b5461243e9190614362565b111561244957600080fd5b601d5461245533611a77565b101561246057600080fd5b601c54610100900460ff161561248c573360009081526022602052604090205481111561248c57600080fd5b60208054336000908152602390925260409091205410156124b857336000908152602460205260408120555b602154156124e857602154336000908152602460205260409020546124dd9083614362565b11156124e857600080fd5b602554600090610100900460ff1615612503575060255460ff165b6001546040516001600160a01b03909116903480156108fc02916000818181858888f1935050505015801561253c573d6000803e3d6000fd5b5060005b8281101561266c57601954604051631381ebf360e31b81526000600482018190526024820181905260ff85166044830152436064830152916001600160a01b031690639c0f5f9890608401602060405180830381600087803b1580156125a557600080fd5b505af11580156125b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125dd919061408d565b90506125f160008060008460008833612994565b50601b80549060006126028361443c565b9091555050601c54610100900460ff161561263857336000908152602260205260408120805491612632836143f0565b91905055505b3360009081526024602052604081208054916126538361443c565b91905055505080806126649061443c565b915050612540565b505060208054336000908152602390925260409091205550565b60008060008060008060008060008060008060168d815481106126ab576126ab6144ad565b6000918252602082206003909102018054436001600160401b03600160881b8304811691909111159f50919350600160481b900416156126ec575060028101545b8160010160049054906101000a900461ffff1661ffff169b508160000160119054906101000a90046001600160401b03166001600160401b03169a508160000160019054906101000a90046001600160401b031699508160000160099054906101000a90046001600160401b031698508160000160199054906101000a900463ffffffff1663ffffffff1697508160010160009054906101000a900463ffffffff1663ffffffff1696508160010160069054906101000a900461ffff1661ffff1695508160000160119054906101000a90046001600160401b03166001600160401b031694508093508160000160009054906101000a900460ff169250505091939597999b90929496989a50565b612802612c65565b6001600160a01b031661281d6010546001600160a01b031690565b6001600160a01b0316146128735760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611081565b6001600160a01b0381166128d85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401611081565b6118fa8161340b565b60003330141561293857600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b0316915061293b9050565b50335b90565b3b151590565b60006001600160e01b031982166380ac58cd60e01b148061297557506001600160e01b03198216635b5e139f60e01b145b80610ecb57506301ffc9a760e01b6001600160e01b0319831614610ecb565b60008763ffffffff1688146129a857600080fd5b8663ffffffff1687146129ba57600080fd5b8561ffff1686146129ca57600080fd5b60006129d760028861437a565b9050600d8161ffff1611156129ea5750600d5b600085156129f55750425b60006040518061012001604052808760ff168152602001426001600160401b03168152602001836001600160401b0316815260200160006001600160401b031681526020018c63ffffffff1681526020018b63ffffffff1681526020018461ffff1681526020018a61ffff16815260200189815250905060006016805490509050601682908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a8154816001600160401b0302191690836001600160401b0316021790555060408201518160000160096101000a8154816001600160401b0302191690836001600160401b0316021790555060608201518160000160116101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160000160196101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160006101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160046101000a81548161ffff021916908361ffff16021790555060e08201518160010160066101000a81548161ffff021916908361ffff160217905550610100820151816002015550508063ffffffff168114612bfd57600080fd5b612c07868261358d565b7fcbdde9319d4c5a92ce42b94fcce19f6419d9227af07758b008752acd4b5fa9cc818360200151604051612c4e9291909182526001600160401b0316602082015260400190565b60405180910390a19b9a5050505050505050505050565b6000612c6f6128e1565b905090565b600081815260076020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612ca9826118fd565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006001600160a01b038616612d485760405162461bcd60e51b815260206004820152602560248201527f4e61746976654d6574615472616e73616374696f6e3a20494e56414c49445f5360448201526424a3a722a960d91b6064820152608401611081565b6001612d5b612d56876135a7565b613624565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa158015612da9573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b031614905095945050505050565b60006121e58284614362565b6000818152600560205260408120546001600160a01b0316612e575760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401611081565b6000612e62836118fd565b9050806001600160a01b0316846001600160a01b03161480612e9d5750836001600160a01b0316612e928461100c565b6001600160a01b0316145b806123bc57506123bc81856122f4565b826001600160a01b0316612ec0826118fd565b6001600160a01b031614612f285760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401611081565b6001600160a01b038216612f8a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401611081565b612f95838383613654565b612fa0600082612c74565b6001600160a01b0383166000908152600660205260408120805460019290612fc99084906143ad565b90915550506001600160a01b0382166000908152600660205260408120805460019290612ff7908490614362565b909155505060008181526005602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000546001600160a01b0316331461306f57600080fd5b600254600160a01b900460ff1661308557600080fd5b6002805460ff60a01b19169055565b6000818414156130a6575060006123bc565b600285015415806130b957506002830154155b156130c6575060006123bc565b8454600160481b90046001600160401b031615806130f357508254600160481b90046001600160401b0316155b15613100575060006123bc565b8454600160c81b900463ffffffff168214806131255750600185015463ffffffff1682145b15613132575060006123bc565b8254600160c81b900463ffffffff168414806131575750600183015463ffffffff1684145b15613164575060006123bc565b8254600160c81b900463ffffffff16158061318b57508454600160c81b900463ffffffff16155b15613198575060016123bc565b84548354600160c81b9182900463ffffffff908116929091041614806131d3575060018501548354600160c81b900463ffffffff9081169116145b156131e0575060006123bc565b8454600184015463ffffffff908116600160c81b90920416148061321557506001808601549084015463ffffffff9081169116145b15613222575060006123bc565b506001949350505050565b6000826001600160a01b0316613242836118fd565b6001600160a01b0316149392505050565b60008060168481548110613269576132696144ad565b9060005260206000209060030201905060006016848154811061328e5761328e6144ad565b6000918252602090912060018085015460039093029091019081015490925061ffff660100000000000092839004811692909104168110156132df575060018101546601000000000000900461ffff165b6001546040516001600160a01b03909116903480156108fc02916000818181858888f19350505050158015613318573d6000803e3d6000fd5b50601954600284810154908401548554604051631381ebf360e31b815260048101939093526024830191909152600060448301819052600160881b9091046001600160401b03166064830152916001600160a01b031690639c0f5f9890608401602060405180830381600087803b15801561339257600080fd5b505af11580156133a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ca919061408d565b905060006133ec88886133de866001614345565b61ffff168560008033612994565b90506133f78561370c565b6134008461370c565b979650505050505050565b601080546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b613468848484612ead565b613474848484846137ec565b61144d5760405162461bcd60e51b8152600401611081906142a2565b6060816134b45750506040805180820190915260018152600360fc1b602082015290565b8160005b81156134de57806134c88161443c565b91506134d79050600a8361437a565b91506134b8565b6000816001600160401b038111156134f8576134f86144c3565b6040519080825280601f01601f191660200182016040528015613522576020820181803683370190505b5090505b84156123bc576135376001836143ad565b9150613544600a86614457565b61354f906030614362565b60f81b818381518110613564576135646144ad565b60200101906001600160f81b031916908160001a905350613586600a8661437a565b9450613526565b6116298282604051806020016040528060008152506138fd565b60006040518060800160405280604381526020016145136043913980516020918201208351848301516040808701518051908601209051613607950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061362f600e5490565b60405161190160f01b6020820152602281019190915260428101839052606201613607565b6001600160a01b0383166136af576136aa81600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b6136d2565b816001600160a01b0316836001600160a01b0316146136d2576136d28382613930565b6001600160a01b0382166136e9576111c9816139cd565b826001600160a01b0316826001600160a01b0316146111c9576111c98282613a7c565b6015546001820154439190601390640100000000900461ffff16600e8110613736576137366144ad565b600891828204019190066004029054906101000a900463ffffffff1663ffffffff16613762919061437a565b61376c9190614362565b815467ffffffffffffffff60881b1916600160881b6001600160401b0392909216919091021781556001810154600d64010000000090910461ffff1610156118fa57600181810180546004906137cf908490640100000000900461ffff16614345565b92506101000a81548161ffff021916908361ffff16021790555050565b60006001600160a01b0384163b156138f557836001600160a01b031663150b7a02613815612c65565b8786866040518563ffffffff1660e01b8152600401613837949392919061420e565b602060405180830381600087803b15801561385157600080fd5b505af1925050508015613881575060408051601f3d908101601f1916820190925261387e91810190613ff2565b60015b6138db573d8080156138af576040519150601f19603f3d011682016040523d82523d6000602084013e6138b4565b606091505b5080516138d35760405162461bcd60e51b8152600401611081906142a2565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506123bc565b5060016123bc565b6139078383613ac0565b61391460008484846137ec565b6111c95760405162461bcd60e51b8152600401611081906142a2565b6000600161393d84611a77565b61394791906143ad565b6000838152600a602052604090205490915080821461399a576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b546000906139df906001906143ad565b6000838152600c6020526040812054600b8054939450909284908110613a0757613a076144ad565b9060005260206000200154905080600b8381548110613a2857613a286144ad565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b805480613a6057613a60614497565b6001900381819060005260206000200160009055905550505050565b6000613a8783611a77565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b6001600160a01b038216613b165760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401611081565b6000818152600560205260409020546001600160a01b031615613b7b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401611081565b613b8760008383613654565b6001600160a01b0382166000908152600660205260408120805460019290613bb0908490614362565b909155505060008181526005602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054613c1a90614407565b90600052602060002090601f016020900481019282613c3c5760008555613c82565b82601f10613c5557805160ff1916838001178555613c82565b82800160010185558215613c82579182015b82811115613c82578251825591602001919060010190613c67565b50613c8e929150613c92565b5090565b5b80821115613c8e5760008155600101613c93565b60006001600160401b0380841115613cc157613cc16144c3565b604051601f8501601f19908116603f01168101908282118183101715613ce957613ce96144c3565b81604052809350858152868686011115613d0257600080fd5b858560208301376000602087830101525050509392505050565b600082601f830112613d2d57600080fd5b6121e583833560208501613ca7565b803560ff81168114613d4d57600080fd5b919050565b600060208284031215613d6457600080fd5b81356121e5816144d9565b60008060408385031215613d8257600080fd5b8235613d8d816144d9565b91506020830135613d9d816144d9565b809150509250929050565b600080600060608486031215613dbd57600080fd5b8335613dc8816144d9565b92506020840135613dd8816144d9565b929592945050506040919091013590565b60008060008060808587031215613dff57600080fd5b8435613e0a816144d9565b93506020850135613e1a816144d9565b92506040850135915060608501356001600160401b03811115613e3c57600080fd5b613e4887828801613d1c565b91505092959194509250565b60008060408385031215613e6757600080fd5b8235613e72816144d9565b91506020830135613d9d816144ee565b600080600080600060a08688031215613e9a57600080fd5b8535613ea5816144d9565b945060208601356001600160401b03811115613ec057600080fd5b613ecc88828901613d1c565b9450506040860135925060608601359150613ee960808701613d3c565b90509295509295909350565b60008060408385031215613f0857600080fd5b8235613f13816144d9565b946020939093013593505050565b600080600060408486031215613f3657600080fd5b83356001600160401b0380821115613f4d57600080fd5b818601915086601f830112613f6157600080fd5b813581811115613f7057600080fd5b8760208260051b8501011115613f8557600080fd5b6020928301989097509590910135949350505050565b600060208284031215613fad57600080fd5b81356121e5816144ee565b600060208284031215613fca57600080fd5b81516121e5816144ee565b600060208284031215613fe757600080fd5b81356121e5816144fc565b60006020828403121561400457600080fd5b81516121e5816144fc565b60006020828403121561402157600080fd5b81516121e5816144d9565b60006020828403121561403e57600080fd5b81356001600160401b0381111561405457600080fd5b8201601f8101841361406557600080fd5b6123bc84823560208401613ca7565b60006020828403121561408657600080fd5b5035919050565b60006020828403121561409f57600080fd5b5051919050565b600080600080608085870312156140bc57600080fd5b8435935060208501356140ce816144d9565b925060408501356140de816144ee565b91506140ec60608601613d3c565b905092959194509250565b6000806040838503121561410a57600080fd5b50508035926020909101359150565b60006020828403121561412b57600080fd5b6121e582613d3c565b6000815180845261414c8160208601602086016143c4565b601f01601f19169290920160200192915050565b600082516141728184602087016143c4565b9190910192915050565b6000835161418e8184602088016143c4565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b600083516141c58184602088016143c4565b8351908301906141d98183602088016143c4565b01949350505050565b6001600160a01b0384811682528316602082015260606040820181905260009061170590830184614134565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061424190830184614134565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561428357835183529284019291840191600101614267565b50909695505050505050565b6020815260006121e56020830184614134565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b600061ffff8083168185168083038211156141d9576141d961446b565b600082198211156143755761437561446b565b500190565b60008261438957614389614481565b500490565b60008160001904831182151516156143a8576143a861446b565b500290565b6000828210156143bf576143bf61446b565b500390565b60005b838110156143df5781810151838201526020016143c7565b8381111561144d5750506000910152565b6000816143ff576143ff61446b565b506000190190565b600181811c9082168061441b57607f821691505b60208210811415611cca57634e487b7160e01b600052602260045260246000fd5b60006000198214156144505761445061446b565b5060010190565b60008261446657614466614481565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146118fa57600080fd5b80151581146118fa57600080fd5b6001600160e01b0319811681146118fa57600080fdfe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529a2646970667358221220516b3a64985c71ab5d00d69b85886eac17d225e5e77de1199fd2e96eee460ac464736f6c63430008070033

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

85732:2950:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50222:224;;;;;;;;;;-1:-1:-1;50222:224:0;;;;;:::i;:::-;;:::i;:::-;;;12366:14:1;;12359:22;12341:41;;12329:2;12314:18;50222:224:0;;;;;;;;79442:32;;;;;;;;;;;;;;;;;;;13509:25:1;;;13497:2;13482:18;79442:32:0;13363:177:1;80672:169:0;;;;;;;;;;-1:-1:-1;80672:169:0;;;;;:::i;:::-;;:::i;:::-;;78927:55;;;;;;;;;;;;78977:5;78927:55;;85355:368;;;;;;;;;;-1:-1:-1;85355:368:0;;;;;:::i;:::-;;:::i;59087:25::-;;;;;;;;;;-1:-1:-1;59087:25:0;;;;-1:-1:-1;;;;;59087:25:0;;;;;;-1:-1:-1;;;;;10218:32:1;;;10200:51;;10188:2;10173:18;59087:25:0;10054:203:1;79058:32:0;;;;;;;;;;;;;;;;38114:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;79347:35::-;;;;;;;;;;-1:-1:-1;79347:35:0;;;;;;;;;;;39673:221;;;;;;;;;;-1:-1:-1;39673:221:0;;;;;:::i;:::-;;:::i;39196:411::-;;;;;;;;;;-1:-1:-1;39196:411:0;;;;;:::i;:::-;;:::i;59055:25::-;;;;;;;;;;-1:-1:-1;59055:25:0;;;;-1:-1:-1;;;;;59055:25:0;;;11070:1151;;;;;;:::i;:::-;;:::i;82237:120::-;;;;;;;;;;-1:-1:-1;82237:120:0;;;;;:::i;:::-;-1:-1:-1;;;;;82326:23:0;82303:4;82326:23;;;:13;:23;;;;;;;82237:120;518:43;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;518:43:0;;;;;79260:32;;;;;;;;;;-1:-1:-1;79260:32:0;;;;;;;;81725:38;;;;;;;;;;-1:-1:-1;81725:38:0;;;;;;;;;;;50862:113;;;;;;;;;;-1:-1:-1;50950:10:0;:17;50862:113;;66565:31;;;;;;;;;;;;;;;;81989:240;;;;;;;;;;-1:-1:-1;81989:240:0;;;;;:::i;:::-;;:::i;80975:98::-;;;;;;;;;;-1:-1:-1;80975:98:0;;;;;:::i;:::-;;:::i;1527:101::-;;;;;;;;;;-1:-1:-1;1605:15:0;;1527:101;;40563:339;;;;;;;;;;-1:-1:-1;40563:339:0;;;;;:::i;:::-;;:::i;59859:132::-;;;;;;;;;;-1:-1:-1;59859:132:0;;;;;:::i;:::-;;:::i;60429:::-;;;;;;;;;;-1:-1:-1;60429: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;50530:256;;;;;;;;;;-1:-1:-1;50530:256:0;;;;;:::i;:::-;;:::i;86577:110::-;;;;;;;;;;-1:-1:-1;86577:110:0;;;;;:::i;:::-;;:::i;1636:161::-;;;;;;;;;;-1:-1:-1;1750:9:0;1636:161;;87119:188;;;;;;;;;;;;;:::i;40973:185::-;;;;;;;;;;-1:-1:-1;40973:185:0;;;;;:::i;:::-;;:::i;72119:384::-;;;;;;;;;;-1:-1:-1;72119:384:0;;;;;:::i;:::-;;:::i;60140:140::-;;;;;;;;;;-1:-1:-1;60140:140:0;;;;;:::i;:::-;;:::i;51052:233::-;;;;;;;;;;-1:-1:-1;51052:233:0;;;;;:::i;:::-;;:::i;69303:84::-;;;;;;;;;;-1:-1:-1;69303:84:0;;;;;:::i;:::-;;:::i;64986:142::-;;;;;;;;;;-1:-1:-1;64986:142:0;;;;;:::i;:::-;;:::i;80293:103::-;;;;;;;;;;;;;:::i;59210:26::-;;;;;;;;;;-1:-1:-1;59210:26:0;;;;-1:-1:-1;;;59210:26:0;;;;;;79683:35;;;;;;;;;;;;;;;;87315:114;;;;;;;;;;;;;:::i;37808:239::-;;;;;;;;;;-1:-1:-1;37808:239:0;;;;;:::i;:::-;;:::i;81634:33::-;;;;;;;;;;-1:-1:-1;81634:33:0;;;;;;;;;;;24692:4:1;24680:17;;;24662:36;;24650:2;24635:18;81634:33:0;24520:184:1;73892:1128:0;;;;;;:::i;:::-;;:::i;37538:208::-;;;;;;;;;;-1:-1:-1;37538:208:0;;;;;:::i;:::-;;:::i;17813:94::-;;;;;;;;;;;;;:::i;79778:46::-;;;;;;;;;;;;;;;;64579:35;;;;;;;;;;;;;;;;61088:83;;;;;;;;;;;;;:::i;65719:711::-;;;;;;;;;;-1:-1:-1;65719:711:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;77856:803::-;;;;;;:::i;:::-;;:::i;17162:87::-;;;;;;;;;;-1:-1:-1;17235:6:0;;-1:-1:-1;;;;;17235:6:0;17162:87;;69001:84;;;;;;;;;;-1:-1:-1;69001:84:0;;;;;:::i;:::-;;:::i;86695:125::-;;;;;;;;;;-1:-1:-1;86695:125:0;;;;;:::i;:::-;;:::i;38283:104::-;;;;;;;;;;;;;:::i;64082:410::-;;;;;;;;;;-1:-1:-1;64082:410:0;;;;;:::i;:::-;;:::i;:::-;;;24497:10:1;24485:23;;;24467:42;;24455:2;24440:18;64082:410:0;24323:192:1;39966:295:0;;;;;;;;;;-1:-1:-1;39966:295:0;;;;;:::i;:::-;;:::i;79878:32::-;;;;;;;;;;;;;;;;59119:25;;;;;;;;;;-1:-1:-1;59119:25:0;;;;-1:-1:-1;;;;;59119:25:0;;;80463:103;;;;;;;;;;-1:-1:-1;80463:103:0;;;;;:::i;:::-;;:::i;80127:95::-;;;;;;;;;;-1:-1:-1;80127:95:0;;;;;:::i;:::-;;:::i;81419:101::-;;;;;;;;;;-1:-1:-1;81419:101:0;;;;;:::i;:::-;;:::i;41229:328::-;;;;;;;;;;-1:-1:-1;41229:328:0;;;;;:::i;:::-;;:::i;82511:132::-;;;;;;;;;;-1:-1:-1;82511:132:0;;;;;:::i;:::-;-1:-1:-1;;;;;82605:30:0;82582:4;82605:30;;;:20;:30;;;;;;;82511:132;81772:96;;;;;;;;;;-1:-1:-1;81772:96:0;;;;;:::i;:::-;;:::i;86828:175::-;;;;;;;;;;-1:-1:-1;86828:175:0;;;;;:::i;:::-;;:::i;81876:105::-;;;;;;;;;;-1:-1:-1;81876:105:0;;;;;:::i;:::-;;:::i;69593:223::-;;;;;;;;;;-1:-1:-1;69593:223:0;;;;;:::i;:::-;;:::i;86476:93::-;;;;;;;;;;;;;:::i;79539:37::-;;;;;;;;;;;;;;;;67001:396;;;;;;;;;;-1:-1:-1;67001:396:0;;;;;:::i;:::-;;:::i;81216:99::-;;;;;;;;;;-1:-1:-1;81216:99:0;;;;;:::i;:::-;;:::i;78869:51::-;;;;;;;;;;;;78916:4;78869:51;;87011:100;;;;;;;;;;;;;:::i;57318:445::-;;;;;;;;;;-1:-1:-1;57318:445:0;;;;;:::i;:::-;;:::i;82369:130::-;;;;;;;;;;-1:-1:-1;82369:130:0;;;;;:::i;:::-;-1:-1:-1;;;;;82459:32:0;82436:4;82459:32;;;:22;:32;;;;;;;82369:130;82651:2444;;;;;;:::i;:::-;;:::i;87570:1109::-;;;;;;;;;;-1:-1:-1;87570:1109:0;;;;;:::i;:::-;;:::i;:::-;;;;12832:14:1;;12825:22;12807:41;;12879:2;12864:18;;12857:34;;;;12907:18;;;12900:34;;;;-1:-1:-1;;;;;13007:15:1;;;13002:2;12987:18;;12980:43;13060:15;;;;13054:3;13039:19;;13032:44;13107:3;13092:19;;13085:35;;;;13151:3;13136:19;;13129:35;13195:3;13180:19;;13173:35;13239:3;13224:19;;13217:35;13283:3;13268:19;;13261:35;13346:4;13333:18;13327:3;13312:19;;13305:47;12794:3;12779:19;87570:1109:0;12393:965:1;79183:31:0;;;;;;;;;;;;;;;;18062:192;;;;;;;;;;-1:-1:-1;18062:192:0;;;;;:::i;:::-;;:::i;66605:31::-;;;;;;;;;;;;;;;;66756:40;;;;;;;;;;-1:-1:-1;66756:40:0;;;;-1:-1:-1;;;;;66756: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;80672:169::-;59479:10;;-1:-1:-1;;;;;59479:10:0;59465;:24;59457:33;;;;;;78977:5:::1;80769:4;80750:16;;:23;;;;:::i;:::-;:50;;80741:60;;;::::0;::::1;;80812:14;:21:::0;80672:169::o;85355:368::-;59479:10;;-1:-1:-1;;;;;59479:10:0;59465;:24;59457:33;;;;;;-1:-1:-1;;;;;85479:21:0;::::1;85475:74;;85527:10;::::0;-1:-1:-1;;;;;85527:10:0::1;::::0;-1:-1:-1;85475:74:0::1;78916:4;85569:17;;:40;85561:49;;;::::0;::::1;;85623:17;:19:::0;;;:17:::1;:19;::::0;::::1;:::i;:::-;;;;;;85655:60;85669:1;85672::::0;85675::::1;85678:6;85686:8;85696:9;85707:7;85655:13;:60::i;:::-;;85355:368:::0;;;;:::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;;20811:2:1;39769:73:0;;;20793:21:1;20850:2;20830:18;;;20823:30;20889:34;20869:18;;;20862:62;-1:-1:-1;;;20940:18:1;;;20933:42;20992: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;;22397:2:1;39327:57:0;;;22379:21:1;22436:2;22416:18;;;22409:30;22475:34;22455:18;;;22448:62;-1:-1:-1;;;22526:18:1;;;22519:31;22567:19;;39327:57:0;22195: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;;19204:2:1;39397:168:0;;;19186:21:1;19243:2;19223:18;;;19216:30;19282:34;19262:18;;;19255:62;19353:26;19333:18;;;19326:54;19397:19;;39397:168:0;19002: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;;21995:2:1;11493:128:0;;;21977:21:1;22034:2;22014:18;;;22007:30;22073:34;22053:18;;;22046:62;-1:-1:-1;;;22124:18:1;;;22117:31;22165:19;;11493:128:0;21793: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;;16912:2:1;12135:48:0;;;16894:21:1;16951:2;16931:18;;;16924:30;16990;16970:18;;;16963:58;17038:18;;12135:48:0;16710:352:1;12135:48:0;12203:10;11070:1151;-1:-1:-1;;;;;;;;11070:1151:0:o;81989:240::-;59479:10;;-1:-1:-1;;;;;59479:10:0;59465;:24;59457:33;;;;;;82105:6:::1;82100:122;82117:23:::0;;::::1;82100:122;;;82196:14;82162:13;:30;82176:12;;82189:1;82176:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;82162:30:0::1;-1:-1:-1::0;;;;;82162:30:0::1;;;;;;;;;;;;;:48;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;82142:3:0;;-1:-1:-1;82142:3:0::1;::::0;::::1;:::i;:::-;;;;82100:122;;;;81989:240:::0;;;:::o;80975:98::-;59479:10;;-1:-1:-1;;;;;59479:10:0;59465;:24;59457:33;;;;;;81044:14:::1;:21:::0;80975:98::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;59859:132::-;59297:10;;-1:-1:-1;;;;;59297:10:0;59283;:24;59275:33;;;;;;-1:-1:-1;;;;;59928:21:0;::::1;59920:30;;;::::0;::::1;;59963:10;:20:::0;;-1:-1:-1;;;;;;59963:20:0::1;-1:-1:-1::0;;;;;59963:20:0;;;::::1;::::0;;;::::1;::::0;;59859:132::o;60429:::-;59297:10;;-1:-1:-1;;;;;59297:10:0;59283;:24;59275:33;;;;;;-1:-1:-1;;;;;60498:21:0;::::1;60490:30;;;::::0;::::1;;60533:10;:20:::0;;-1:-1:-1;;;;;;60533:20:0::1;-1:-1:-1::0;;;;;60533:20:0;;;::::1;::::0;;;::::1;::::0;;60429:132::o;50530:256::-;50627:7;50663:23;50680:5;50663:16;:23::i;:::-;50655:5;:31;50647:87;;;;-1:-1:-1;;;50647:87:0;;15674:2:1;50647:87:0;;;15656:21:1;15713:2;15693:18;;;15686:30;15752:34;15732:18;;;15725:62;-1:-1:-1;;;15803:18:1;;;15796:41;15854:19;;50647:87:0;15472:407:1;50647:87:0;-1:-1:-1;;;;;;50752:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;50530:256::o;86577:110::-;59587:10;;-1:-1:-1;;;;;59587:10:0;59573;:24;;:65;;-1:-1:-1;59628:10:0;;-1:-1:-1;;;;;59628:10:0;59614;:24;59573:65;:106;;;-1:-1:-1;59669:10:0;;-1:-1:-1;;;;;59669:10:0;59655;:24;59573:106;59551:139;;;;;;86658:21;;::::1;::::0;:7:::1;::::0;:21:::1;::::0;::::1;::::0;::::1;:::i;:::-;;86577:110:::0;:::o;87119:188::-;59297:10;;-1:-1:-1;;;;;59297:10:0;59283;:24;59275:33;;;;;;60904:6:::1;::::0;-1:-1:-1;;;60904:6:0;::::1;;;60896:15;;;::::0;::::1;;87200:12:::2;::::0;-1:-1:-1;;;;;87200:12:0::2;87184:44;;;::::0;::::2;;87284:15;:13;:15::i;:::-;87119:188::o:0;40973:185::-;41111:39;41128:4;41134:2;41138:7;41111:39;;;;;;;;;;;;:16;:39::i;72119:384::-;72230:4;72273:1;72260:10;:14;72252:23;;;;;;72307:1;72294:10;:14;72286:23;;;;;;72320:22;72345:6;72352:10;72345:18;;;;;;;;:::i;:::-;;;;;;;;;;;72320:43;;72374:22;72399:6;72406:10;72399:18;;;;;;;;:::i;:::-;;;;;;;;;;;72374:43;;72435:60;72454:7;72463:10;72475:7;72484:10;72435:18;:60::i;:::-;72428:67;72119:384;-1:-1:-1;;;;;72119:384:0:o;60140:140::-;59297:10;;-1:-1:-1;;;;;59297:10:0;59283;:24;59275:33;;;;;;-1:-1:-1;;;;;60217:21:0;::::1;60209:30;;;::::0;::::1;;60252:10;:20:::0;;-1:-1:-1;;;;;;60252:20:0::1;-1:-1:-1::0;;;;;60252:20:0;;;::::1;::::0;;;::::1;::::0;;60140: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;;23217:2:1;51147:95:0;;;23199:21:1;23256:2;23236:18;;;23229:30;23295:34;23275:18;;;23268:62;-1:-1:-1;;;23346:18:1;;;23339:42;23398:19;;51147:95:0;23015:408:1;51147:95:0;51260:10;51271:5;51260:17;;;;;;;;:::i;:::-;;;;;;;;;51253:24;;51052:233;;;:::o;69303:84::-;59479:10;;-1:-1:-1;;;;;59479:10:0;59465;:24;59457:33;;;;;;69365:8:::1;:14:::0;69303:84::o;64986:142::-;59587:10;;-1:-1:-1;;;;;59587:10:0;59573;:24;;:65;;-1:-1:-1;59628:10:0;;-1:-1:-1;;;;;59628:10:0;59614;:24;59573:65;:106;;;-1:-1:-1;59669:10:0;;-1:-1:-1;;;;;59669:10:0;59655;:24;59573:106;59551:139;;;;;;65074:9:::1;:12:::0;::::1;;65067:19:::0;::::1;65059:28;;;::::0;::::1;;65098:15;:22:::0;64986:142::o;80293:103::-;59587:10;;-1:-1:-1;;;;;59587:10:0;59573;:24;;:65;;-1:-1:-1;59628:10:0;;-1:-1:-1;;;;;59628:10:0;59614;:24;59573:65;:106;;;-1:-1:-1;59669:10:0;;-1:-1:-1;;;;;59669:10:0;59655;:24;59573:106;59551:139;;;;;;80373:15:::1;80354:16;:34:::0;80293:103::o;87315:114::-;59388:10;;-1:-1:-1;;;;;59388:10:0;59374;:24;59366:33;;;;;;87378:10:::1;::::0;87370:51:::1;::::0;-1:-1:-1;;;;;87378:10:0;;::::1;::::0;87399:21:::1;87370:51:::0;::::1;;;::::0;87378:10:::1;87370:51:::0;87378:10;87370:51;87399:21;87378:10;87370:51;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;87315:114::o:0;37808:239::-;37880:7;37916:16;;;:7;:16;;;;;;-1:-1:-1;;;;;37916:16:0;37951:19;37943:73;;;;-1:-1:-1;;;37943:73:0;;20040:2:1;37943:73:0;;;20022:21:1;20079:2;20059:18;;;20052:30;20118:34;20098:18;;;20091:62;-1:-1:-1;;;20169:18:1;;;20162:39;20218:19;;37943:73:0;19838:405:1;73892:1128:0;60757:6;;-1:-1:-1;;;60757:6:0;;;;60756:7;60748:16;;;;;;74078:8:::1;;74065:9;:21;;74057:30;;;::::0;::::1;;74164:29;74170:10;74182;74164:5;:29::i;:::-;74156:38;;;::::0;::::1;;74213:29;74219:10;74231;74213:5;:29::i;:::-;74205:38;;;::::0;::::1;;74306:22;74331:6;74338:10;74331:18;;;;;;;;:::i;:::-;;;;;;;;;;;74306:43;;74454:24;74470:7;67849:22:::0;-1:-1:-1;;;;;67882:12:0;67849:46;;-1:-1:-1;;;67849:22:0;;;;:46;;;67519:384;74454:24:::1;74446:33;;;::::0;::::1;;74542:22;74567:6;74574:10;74567:18;;;;;;;;:::i;:::-;;;;;;;;;;;74542:43;;74692:24;74708:7;67849:22:::0;-1:-1:-1;;;;;67882:12:0;67849:46;;-1:-1:-1;;;67849:22:0;;;;:46;;;67519:384;74692:24:::1;74684:33;;;::::0;::::1;;74798:123;74831:7;74853:10;74878:7;74900:10;74798:18;:123::i;:::-;74790:132;;;::::0;::::1;;74978:34;74989:10;75001;74978;:34::i;37538:208::-:0;37610:7;-1:-1:-1;;;;;37638:19:0;;37630:74;;;;-1:-1:-1;;;37630:74:0;;19629:2:1;37630:74:0;;;19611:21:1;19668:2;19648:18;;;19641:30;19707:34;19687:18;;;19680:62;-1:-1:-1;;;19758:18:1;;;19751:40;19808:19;;37630:74:0;19427:406:1;37630:74:0;-1:-1:-1;;;;;;37722:16:0;;;;;:9;:16;;;;;;;37538:208::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;;21224:2:1;17374:68:0;;;21206:21:1;;;21243:18;;;21236:30;21302:34;21282:18;;;21275:62;21354:18;;17374:68:0;21022:356:1;17374:68:0;17878:21:::1;17896:1;17878:9;:21::i;61088:83::-:0;59587:10;;-1:-1:-1;;;;;59587:10:0;59573;:24;;:65;;-1:-1:-1;59628:10:0;;-1:-1:-1;;;;;59628:10:0;59614;:24;59573:65;:106;;;-1:-1:-1;59669:10:0;;-1:-1:-1;;;;;59669:10:0;59655;:24;59573:106;59551:139;;;;;;60757:6:::1;::::0;-1:-1:-1;;;60757:6:0;::::1;;;60756:7;60748:16;;;::::0;::::1;;61150:6:::2;:13:::0;;-1:-1:-1;;;;61150:13:0::2;-1:-1:-1::0;;;61150:13:0::2;::::0;;61088:83::o;65719:711::-;65780:28;65821:18;65842:17;65852:6;65842:9;:17::i;:::-;65821:38;-1:-1:-1;65874:15:0;65870:553;;-1:-1:-1;;65953:16:0;;;65967:1;65953:16;;;;;;;;;65946:23;-1:-1:-1;65719:711:0:o;65870:553::-;66006:23;66046:10;-1:-1:-1;;;;;66032:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;66032:25:0;;66006:51;;66072:19;66110:18;66145:237;66180:14;66193:1;66180:10;:14;:::i;:::-;66166:10;:28;66145:237;;66229:15;66247:39;66267:6;66275:10;66247:19;:39::i;:::-;66229:57;;66327:7;66305:6;66312:11;66305:19;;;;;;;;:::i;:::-;;;;;;;;;;:29;66353:13;;;;:::i;:::-;;;;66210:172;66196:12;;;;;:::i;:::-;;;;66145:237;;;-1:-1:-1;66405:6:0;;65719:711;-1:-1:-1;;;;65719:711:0:o;65870:553::-;65810:620;65719:711;;;:::o;77856:803::-;60757:6;;-1:-1:-1;;;60757:6:0;;;;60756:7;60748:16;;;;;;78020:8:::1;;78007:9;:21;;77999:30;;;::::0;::::1;;78112:26;78118:10;78130:7;78112:5;:26::i;:::-;78104:35;;;::::0;::::1;;78152:26;78181:6;78188:7;78181:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;;::::1;;78277:21:::0;;78181:15;;-1:-1:-1;;;;78277:21:0;::::1;-1:-1:-1::0;;;;;78277:21:0::1;:26:::0;78269:35:::1;;;::::0;::::1;;78317:47:::0;;-1:-1:-1;;;;;78348:15:0::1;78317:47;-1:-1:-1::0;;;78317:47:0::1;-1:-1:-1::0;;78317:47:0;;::::1;;::::0;;-1:-1:-1;78448:10:0;78432:48:::1;::::0;-1:-1:-1;;;;;78448:10:0;;::::1;::::0;78470:9:::1;78432:48:::0;::::1;;;::::0;78317:21:::1;78432:48:::0;78317:21;78432:48;78470:9;78448:10;78432:48;::::1;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;78629:21:0;;78602:49:::1;::::0;;78608:10:::1;11391:51:1::0;;11473:2;11458:18;;11451:34;;;-1:-1:-1;;;78629:21:0;;::::1;-1:-1:-1::0;;;;;78629:21:0::1;11501:18:1::0;;;11494:59;78602:49:0::1;::::0;11379:2:1;11364:18;78602:49:0::1;;;;;;;77957:702;77856:803:::0;:::o;69001:84::-;59479:10;;-1:-1:-1;;;;;59479:10:0;59465;:24;59457:33;;;;;;69063:8:::1;:14:::0;69001:84::o;86695:125::-;59587:10;;-1:-1:-1;;;;;59587:10:0;59573;:24;;:65;;-1:-1:-1;59628:10:0;;-1:-1:-1;;;;;59628:10:0;59614;:24;59573:65;:106;;;-1:-1:-1;59669:10:0;;-1:-1:-1;;;;;59669:10:0;59655;:24;59573:106;59551:139;;;;;;86779:33;;::::1;::::0;:15:::1;::::0;:33:::1;::::0;::::1;::::0;::::1;:::i;38283:104::-:0;38339:13;38372:7;38365:14;;;;;:::i;64082: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;;18031:2:1;40061:62:0;;;18013:21:1;18070:2;18050:18;;;18043:30;18109:27;18089:18;;;18082:55;18154:18;;40061:62:0;17829: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;;;;12366:14:1;12359:22;12341:41;;12329:2;12314:18;;12201:187;40205:48:0;;;;;;;;39966:295;;:::o;80463:103::-;59587:10;;-1:-1:-1;;;;;59587:10:0;59573;:24;;:65;;-1:-1:-1;59628:10:0;;-1:-1:-1;;;;;59628:10:0;59614;:24;59573:65;:106;;;-1:-1:-1;59669:10:0;;-1:-1:-1;;;;;59669:10:0;59655;:24;59573:106;59551:139;;;;;;80535:16:::1;:23:::0;80463:103::o;80127:95::-;59587:10;;-1:-1:-1;;;;;59587:10:0;59573;:24;;:65;;-1:-1:-1;59628:10:0;;-1:-1:-1;;;;;59628:10:0;59614;:24;59573:65;:106;;;-1:-1:-1;59669:10:0;;-1:-1:-1;;;;;59669:10:0;59655;:24;59573:106;59551:139;;;;;;80195:12:::1;:19:::0;;-1:-1:-1;;80195:19:0::1;::::0;::::1;;::::0;;;::::1;::::0;;80127:95::o;81419:101::-;59479:10;;-1:-1:-1;;;;;59479:10:0;59465;:24;59457:33;;;;;;81489:16:::1;:23:::0;81419:101::o;41229:328::-;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;81772:96::-;59587:10;;-1:-1:-1;;;;;59587:10:0;59573;:24;;:65;;-1:-1:-1;59628:10:0;;-1:-1:-1;;;;;59628:10:0;59614;:24;59573:65;:106;;;-1:-1:-1;59669:10:0;;-1:-1:-1;;;;;59669:10:0;59655;:24;59573:106;59551:139;;;;;;81837:16:::1;:23:::0;;-1:-1:-1;;81837:23:0::1;;::::0;;;::::1;::::0;;;::::1;::::0;;81772:96::o;86828:175::-;86894:13;86951:14;:12;:14::i;:::-;86967:26;86984:8;86967:16;:26::i;:::-;86934:60;;;;;;;;;:::i;:::-;;;;;;;;;;;;;86920:75;;86828:175;;;:::o;81876:105::-;59587:10;;-1:-1:-1;;;;;59587:10:0;59573;:24;;:65;;-1:-1:-1;59628:10:0;;-1:-1:-1;;;;;59628:10:0;59614;:24;59573:65;:106;;;-1:-1:-1;59669:10:0;;-1:-1:-1;;;;;59669:10:0;59655;:24;59573:106;59551:139;;;;;;81945:18:::1;:28:::0;;;::::1;;;;-1:-1:-1::0;;81945:28:0;;::::1;::::0;;;::::1;::::0;;81876:105::o;69593:223::-;69681:4;69720:1;69711:6;:10;69703:19;;;;;;69733;69755:6;69762;69755:14;;;;;;;;:::i;:::-;;;;;;;;;;;69733:36;;69787:21;69803:4;67849:22;-1:-1:-1;;;;;67882:12:0;67849:46;;-1:-1:-1;;;67849:22:0;;;;:46;;;67519:384;69787:21;69780:28;69593:223;-1:-1:-1;;;69593:223:0:o;86476:93::-;86521:13;86554:7;86547:14;;;;;:::i;67001:396::-;59297:10;;-1:-1:-1;;;;;59297:10:0;59283;:24;59275:33;;;;;;67078:38:::1;67140:8;67078:71;;67268:17;-1:-1:-1::0;;;;;67268:32:0::1;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67260:43;;;::::0;::::1;;67357:12;:32:::0;;-1:-1:-1;;;;;;67357:32:0::1;-1:-1:-1::0;;;;;67357:32:0;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;67001:396:0:o;81216:99::-;59479:10;;-1:-1:-1;;;;;59479:10:0;59465;:24;59457:33;;;;;;81285:15:::1;:22:::0;;;::::1;;;;-1:-1:-1::0;;81285:22:0;;::::1;::::0;;;::::1;::::0;;81216:99::o;87011:100::-;87055:13;87088:15;87081:22;;;;;:::i;57318:445::-;57572:20;;57616:28;;-1:-1:-1;;;57616:28:0;;-1:-1:-1;;;;;10218:32:1;;;57616:28:0;;;10200:51:1;57443:4:0;;57572:20;;;57608:49;;;;57572:20;;57616:21;;10173: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;82651:2444::-;60757:6;;-1:-1:-1;;;60757:6:0;;;;60756:7;60748:16;;;;;;82811:12:::1;::::0;::::1;;82802:22;;;::::0;::::1;;82947:1;82932:12;:16;82924:25;;;::::0;::::1;;83047:12;83030:14;;:29;;;;:::i;:::-;83017:9;:42;;83008:52;;;::::0;::::1;;83185:14;;83169:12;83150:16;;:31;;;;:::i;:::-;:49;;83141:59;;;::::0;::::1;;78977:5;83304:12;83285:16;;:31;;;;:::i;:::-;:58;;83276:68;;;::::0;::::1;;83481:16;;83456:21;83466:10;83456:9;:21::i;:::-;:41;;83447:51;;;::::0;::::1;;83587:15;::::0;::::1;::::0;::::1;;;83583:97;;;83656:10;83642:25;::::0;;;:13:::1;:25;::::0;;;;;83626:41;::::1;;83618:50;;;::::0;::::1;;83861:16;::::0;;83847:10:::1;83826:32;::::0;;;:20:::1;:32:::0;;;;;;;;:51:::1;83822:121;;;83916:10;83930:1;83893:34:::0;;;:22:::1;:34;::::0;;;;:38;83822:121:::1;84037:16;::::0;:20;84033:130:::1;;84134:16;::::0;84119:10:::1;84096:34;::::0;;;:22:::1;:34;::::0;;;;;84081:49:::1;::::0;:12;:49:::1;:::i;:::-;:69;;84073:78;;;::::0;::::1;;84207:18;::::0;84175:15:::1;::::0;84207:18:::1;::::0;::::1;;;84203:78;;;-1:-1:-1::0;84253:16:0::1;::::0;::::1;;84203:78;84382:10;::::0;84366:48:::1;::::0;-1:-1:-1;;;;;84382:10:0;;::::1;::::0;84404:9:::1;84366:48:::0;::::1;;;::::0;84382:10:::1;84366:48:::0;84382:10;84366:48;84404:9;84382:10;84366:48;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;84432:6;84427:515;84448:12;84444:1;:16;84427:515;;;84577:12;::::0;:54:::1;::::0;-1:-1:-1;;;84577:54:0;;84558:16:::1;84577:54;::::0;::::1;15072:25:1::0;;;15113:18;;;15106:34;;;15188:4;15176:17;;15156:18;;;15149:45;84618:12:0::1;15210:18:1::0;;;15203:34;84558:16:0;-1:-1:-1;;;;;84577:12:0::1;::::0;:23:::1;::::0;15044:19:1;;84577:54:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;84558:73;;84660:62;84674:1;84677::::0;84680::::1;84683:8;84693:5;84700:9;84711:10;84660:13;:62::i;:::-;-1:-1:-1::0;84751:16:0::1;:18:::0;;;:16:::1;:18;::::0;::::1;:::i;:::-;::::0;;;-1:-1:-1;;84802:15:0::1;::::0;::::1;::::0;::::1;;;84798:82;;;84851:10;84837:25;::::0;;;:13:::1;:25;::::0;;;;:27;;;::::1;::::0;::::1;:::i;:::-;;;;;;84798:82;84917:10;84894:34;::::0;;;:22:::1;:34;::::0;;;;:36;;;::::1;::::0;::::1;:::i;:::-;;;;;;84467:475;84462:3;;;;;:::i;:::-;;;;84427:515;;;-1:-1:-1::0;;85061:16:0::1;::::0;;85047:10:::1;85026:32;::::0;;;:20:::1;:32:::0;;;;;;;:51;-1:-1:-1;82651:2444:0:o;87570:1109::-;87662:12;87685:21;87717:20;87748:16;87775;87802:17;87830;87858:18;87887:24;87922:13;87946:15;87982:19;88004:6;88011:3;88004:11;;;;;;;;:::i;:::-;;;;;;;;;;;;;88039:21;;88064:12;-1:-1:-1;;;;;;;;88039:21:0;;;;:37;;;;;;-1:-1:-1;88004:11:0;;-1:-1:-1;;;;88126:14:0;;;:18;88122:74;;-1:-1:-1;88174:10:0;;;;88122:74;88232:4;:18;;;;;;;;;;;;88224:27;;88208:43;;88285:4;:21;;;;;;;;;;-1:-1:-1;;;;;88285:21:0;-1:-1:-1;;;;;88277:30:0;88262:45;;88337:4;:14;;;;;;;;;;-1:-1:-1;;;;;88337:14:0;88318:34;;88382:4;:14;;;;;;;;;;-1:-1:-1;;;;;88382:14:0;88363:34;;88428:4;:14;;;;;;;;;;;;88420:23;;88408:35;;88474:4;:14;;;;;;;;;;;;88466:23;;88454:35;;88521:4;:15;;;;;;;;;;;;88513:24;;88500:37;;88575:4;:21;;;;;;;;;;-1:-1:-1;;;;;88575:21:0;-1:-1:-1;;;;;88567:30:0;88548:49;;88616:11;88608:19;;88656:4;:14;;;;;;;;;;;;88638:33;;87969:710;;87570:1109;;;;;;;;;;;;;:::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;;21224:2:1;17374:68:0;;;21206:21:1;;;21243:18;;;21236:30;21302:34;21282:18;;;21275:62;21354:18;;17374:68:0;21022:356:1;17374:68:0;-1:-1:-1;;;;;18151:22:0;::::1;18143:73;;;::::0;-1:-1:-1;;;18143:73:0;;16505:2:1;18143:73:0::1;::::0;::::1;16487:21:1::0;16544:2;16524:18;;;16517:30;16583:34;16563:18;;;16556:62;-1:-1:-1;;;16634:18:1;;;16627:36;16680:19;;18143:73:0::1;16303:402:1::0;18143:73:0::1;18227:19;18237:8;18227:9;:19::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;19208:387::-;19531:20;19579:8;;;19208:387::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;75737:2111;75989:4;76376:10;76361:27;;76347:10;:41;76339:50;;;;;;76437:10;76422:27;;76408:10;:41;76400:50;;;;;;76499:11;76484:28;;76469:11;:43;76461:52;;;;;;76593:20;76623:15;76637:1;76623:11;:15;:::i;:::-;76593:46;;76670:2;76654:13;:18;;;76650:69;;;-1:-1:-1;76705:2:0;76650:69;76731:16;76764:8;76760:75;;;-1:-1:-1;76807:15:0;76760:75;76847:21;76871:385;;;;;;;;76938:10;76871:385;;;;;;76982:15;-1:-1:-1;;;;;76871:385:0;;;;;77024:9;-1:-1:-1;;;;;76871:385:0;;;;;77066:1;-1:-1:-1;;;;;76871:385:0;;;;;77100:10;76871:385;;;;;;77144:10;76871:385;;;;;;77185:13;76871:385;;;;;;77232:11;76871:385;;;;;;76900:6;76871:385;;;76847:409;;77269:19;77291:6;:13;;;;77269:35;;77315:6;77327:7;77315:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;77315:20:0;;;;;-1:-1:-1;;;;;77315:20:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;77315:20:0;;;;;-1:-1:-1;;;;;77315:20:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;77315:20:0;;;;;-1:-1:-1;;;;;77315:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77526:11;77511:28;;77496:11;:43;77488:52;;;;;;77649:27;77659:3;77664:11;77649:9;:27::i;:::-;77727:82;77747:11;77780:7;:17;;;77727:82;;;;;;24219:25:1;;;-1:-1:-1;;;;;24280:31:1;24275:2;24260:18;;24253:59;24207:2;24192:18;;24047:271;77727:82:0;;;;;;;;77829:11;75737:2111;-1:-1:-1;;;;;;;;;;;75737:2111:0:o;57907:161::-;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;;18798:2:1;12957:70:0;;;18780:21:1;18837:2;18817:18;;;18810:30;18876:34;18856:18;;;18849:62;-1:-1:-1;;;18927:18:1;;;18920:35;18972:19;;12957:70:0;18596:401:1;12957:70:0;13081:159;13109:47;13128:27;13148:6;13128:19;:27::i;:::-;13109:18;:47::i;:::-;13081:159;;;;;;;;;;;;14194:25:1;;;;14267:4;14255:17;;14235:18;;;14228:45;14289:18;;;14282:34;;;14332:18;;;14325:34;;;14166: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;;18385:2:1;43471:73:0;;;18367:21:1;18424:2;18404:18;;;18397:30;18463:34;18443:18;;;18436:62;-1:-1:-1;;;18514:18:1;;;18507:42;18566:19;;43471:73:0;18183: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;46353:578::-;46512:4;-1:-1:-1;;;;;46485:31:0;:23;46500:7;46485:14;:23::i;:::-;-1:-1:-1;;;;;46485:31:0;;46477:85;;;;-1:-1:-1;;;46477:85:0;;21585:2:1;46477:85:0;;;21567:21:1;21624:2;21604:18;;;21597:30;21663:34;21643:18;;;21636:62;-1:-1:-1;;;21714:18:1;;;21707:39;21763:19;;46477:85:0;21383:405:1;46477:85:0;-1:-1:-1;;;;;46581:16:0;;46573:65;;;;-1:-1:-1;;;46573:65:0;;17626:2:1;46573:65:0;;;17608:21:1;17665:2;17645:18;;;17638:30;17704:34;17684:18;;;17677:62;-1:-1:-1;;;17755:18:1;;;17748:34;17799:19;;46573:65:0;17424:400:1;46573:65:0;46651:39;46672:4;46678:2;46682:7;46651:20;:39::i;:::-;46755:29;46772:1;46776:7;46755:8;:29::i;:::-;-1:-1:-1;;;;;46797:15:0;;;;;;:9;:15;;;;;:20;;46816:1;;46797:15;:20;;46816:1;;46797:20;:::i;:::-;;;;-1:-1:-1;;;;;;;46828:13:0;;;;;;:9;:13;;;;;:18;;46845:1;;46828:13;:18;;46845:1;;46828:18;:::i;:::-;;;;-1:-1:-1;;46857:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;46857:21:0;-1:-1:-1;;;;;46857:21:0;;;;;;;;;46896:27;;46857:16;;46896:27;;;;;;;46353:578;;;:::o;61466:137::-;59297:10;;-1:-1:-1;;;;;59297:10:0;59283;:24;59275:33;;;;;;60904:6:::1;::::0;-1:-1:-1;;;60904:6:0;::::1;;;60896:15;;;::::0;::::1;;61581:6:::2;:14:::0;;-1:-1:-1;;;;61581:14:0::2;::::0;;61466:137::o;70251:1486::-;70460:4;70544:10;70530;:24;70526:69;;;-1:-1:-1;70578:5:0;70571:12;;70526:69;70650:14;;;;:19;;:42;;-1:-1:-1;70673:14:0;;;;:19;70650:42;70646:87;;;-1:-1:-1;70716:5:0;70709:12;;70646:87;70789:18;;-1:-1:-1;;;70789:18:0;;-1:-1:-1;;;;;70789:18:0;:23;;:50;;-1:-1:-1;70816:18:0;;-1:-1:-1;;;70816:18:0;;-1:-1:-1;;;;;70816:18:0;:23;70789:50;70785:95;;;-1:-1:-1;70863:5:0;70856:12;;70785:95;70945:18;;-1:-1:-1;;;70945:18:0;;;;:32;;;:68;;-1:-1:-1;70981:18:0;;;;;;:32;;70945:68;70941:113;;;-1:-1:-1;71037:5:0;71030:12;;70941:113;71068:18;;-1:-1:-1;;;71068:18:0;;;;:32;;;:68;;-1:-1:-1;71104:18:0;;;;;;:32;;71068:68;71064:113;;;-1:-1:-1;71160:5:0;71153:12;;71064:113;71261:18;;-1:-1:-1;;;71261:18:0;;;;:23;;:50;;-1:-1:-1;71288:18:0;;-1:-1:-1;;;71288:18:0;;;;:23;71261:50;71257:94;;;-1:-1:-1;71335:4:0;71328:11;;71257:94;71446:18;;71424;;-1:-1:-1;;;71446:18:0;;;;;;;;71424;;;;;:40;;:84;;-1:-1:-1;71490:18:0;;;;71468;;-1:-1:-1;;;71468:18:0;;71490;71468;;;71490;;71468:40;71424:84;71420:129;;;-1:-1:-1;71532:5:0;71525:12;;71420:129;71587:18;;71565;;;;71587;71565;;;-1:-1:-1;;;71587:18:0;;;;71565:40;;:84;;-1:-1:-1;71631:18:0;;;;;71609;;;;71631;71609;;;71631;;71609:40;71565:84;71561:129;;;-1:-1:-1;71673:5:0;71666:12;;71561:129;-1:-1:-1;71725:4:0;70251:1486;;;;;;:::o;65378:191::-;65505:4;65551:9;-1:-1:-1;;;;;65530:30:0;:17;65538:8;65530:7;:17::i;:::-;-1:-1:-1;;;;;65530:30:0;;;65378:191;-1:-1:-1;;;65378:191:0:o;72662:1222::-;72739:7;72846:22;72871:6;72878:10;72871:18;;;;;;;;:::i;:::-;;;;;;;;;;;72846:43;;72900:22;72925:6;72932:10;72925:18;;;;;;;;:::i;:::-;;;;;;;;;73077;;;;;72925;;;;;;;73110;;;;72925;;-1:-1:-1;73077:18:0;;;;;;;;;73110;;;;:39;-1:-1:-1;73106:102:0;;;-1:-1:-1;73178:18:0;;;;;;;;;73106:102;73291:10;;73275:48;;-1:-1:-1;;;;;73291:10:0;;;;73313:9;73275:48;;;;;73291:10;73275:48;73291:10;73275:48;73313:9;73291:10;73275:48;;;;;;;;;;;;;;;;;;;;-1:-1:-1;73455:12:0;;73479:13;;;;;73494;;;;73512:24;;73455:82;;-1:-1:-1;;;73455:82:0;;;;;23846:25:1;;;;23887:18;;;23880:34;;;;73436:16:0;23930:18:1;;;23923:45;;;-1:-1:-1;;;73512:24:0;;;-1:-1:-1;;;;;73512:24:0;23984:18:1;;;23977:59;73436:16:0;-1:-1:-1;;;;;73455:12:0;;:23;;23818:19:1;;73455:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73436:101;-1:-1:-1;73618:17:0;73638:84;73652:10;73664;73676:13;:9;73688:1;73676:13;:::i;:::-;73638:84;;73691:8;73701:5;73708:1;73711:10;73638:13;:84::i;:::-;73618:104;;73786:25;73803:7;73786:16;:25::i;:::-;73822;73839:7;73822:16;:25::i;:::-;73867:9;72662:1222;-1:-1:-1;;;;;;;72662:1222: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;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;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;;44051:110;44127:26;44137:2;44141:7;44127:26;;;;;;;;;;;;:9;:26::i;12229:410::-;12339:7;10406:100;;;;;;;;;;;;;;;;;10386:127;;;;;;;12493:12;;12528:11;;;;12572:24;;;;;12562:35;;;;;;12412:204;;;;;13776:25:1;;;13832:2;13817:18;;13810:34;;;;-1:-1:-1;;;;;13880:32:1;13875:2;13860:18;;13853:60;13944:2;13929:18;;13922:34;13763:3;13748:19;;13545: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;;;9915:27:1;9958:11;;;9951:27;;;;9994:12;;;9987:28;;;10031:12;;2338:63:0;9657: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;68171:612::-;68411:15;;68387:22;;;;68430:12;;68411:15;68377:9;;68387:22;;;;;68377:33;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;:49;;;;;;:::i;:::-;68376:66;;;;:::i;:::-;68341:102;;-1:-1:-1;;;;68341:102:0;-1:-1:-1;;;;;;;;68341:102:0;;;;;;;;;;;-1:-1:-1;68693:22:0;;;68718:2;68693:22;;;;;;:27;68689:87;;;68763:1;68737:22;;;:27;;:22;;:27;;68763:1;;68737:27;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;68171: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;;44388:321;44518:18;44524:2;44528:7;44518:5;:18::i;:::-;44569:54;44600:1;44604:2;44608:7;44617:5;44569:22;:54::i;:::-;44547:154;;;;-1:-1:-1;;;44547:154:0;;;;;;;:::i;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;;20450:2:1;45117:61:0;;;20432:21:1;;;20469:18;;;20462:30;20528:34;20508:18;;;20501:62;20580:18;;45117:61:0;20248: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;;17269:2:1;45189:58:0;;;17251:21:1;17308:2;17288:18;;;17281:30;17347;17327:18;;;17320:58;17395:18;;45189:58:0;17067: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:156::-;941:20;;1001:4;990:16;;980:27;;970:55;;1021:1;1018;1011:12;970:55;875:156;;;:::o;1036:247::-;1095:6;1148:2;1136:9;1127:7;1123:23;1119:32;1116:52;;;1164:1;1161;1154:12;1116:52;1203:9;1190:23;1222:31;1247:5;1222:31;:::i;1548:388::-;1616:6;1624;1677:2;1665:9;1656:7;1652:23;1648:32;1645:52;;;1693:1;1690;1683:12;1645:52;1732:9;1719:23;1751:31;1776:5;1751:31;:::i;:::-;1801:5;-1:-1:-1;1858:2:1;1843:18;;1830:32;1871:33;1830:32;1871:33;:::i;:::-;1923:7;1913:17;;;1548:388;;;;;:::o;1941:456::-;2018:6;2026;2034;2087:2;2075:9;2066:7;2062:23;2058:32;2055:52;;;2103:1;2100;2093:12;2055:52;2142:9;2129:23;2161:31;2186:5;2161:31;:::i;:::-;2211:5;-1:-1:-1;2268:2:1;2253:18;;2240:32;2281:33;2240:32;2281:33;:::i;:::-;1941:456;;2333:7;;-1:-1:-1;;;2387:2:1;2372:18;;;;2359:32;;1941:456::o;2402:665::-;2497:6;2505;2513;2521;2574:3;2562:9;2553:7;2549:23;2545:33;2542:53;;;2591:1;2588;2581:12;2542:53;2630:9;2617:23;2649:31;2674:5;2649:31;:::i;:::-;2699:5;-1:-1:-1;2756:2:1;2741:18;;2728:32;2769:33;2728:32;2769:33;:::i;:::-;2821:7;-1:-1:-1;2875:2:1;2860:18;;2847:32;;-1:-1:-1;2930:2:1;2915:18;;2902:32;-1:-1:-1;;;;;2946:30:1;;2943:50;;;2989:1;2986;2979:12;2943:50;3012:49;3053:7;3044:6;3033:9;3029:22;3012:49;:::i;:::-;3002:59;;;2402:665;;;;;;;:::o;3072:382::-;3137:6;3145;3198:2;3186:9;3177:7;3173:23;3169:32;3166:52;;;3214:1;3211;3204:12;3166:52;3253:9;3240:23;3272:31;3297:5;3272:31;:::i;:::-;3322:5;-1:-1:-1;3379:2:1;3364:18;;3351:32;3392:30;3351:32;3392:30;:::i;3459:663::-;3561:6;3569;3577;3585;3593;3646:3;3634:9;3625:7;3621:23;3617:33;3614:53;;;3663:1;3660;3653:12;3614:53;3702:9;3689:23;3721:31;3746:5;3721:31;:::i;:::-;3771:5;-1:-1:-1;3827:2:1;3812:18;;3799:32;-1:-1:-1;;;;;3843:30:1;;3840:50;;;3886:1;3883;3876:12;3840:50;3909:49;3950:7;3941:6;3930:9;3926:22;3909:49;:::i;:::-;3899:59;;;4005:2;3994:9;3990:18;3977:32;3967:42;;4056:2;4045:9;4041:18;4028:32;4018:42;;4079:37;4111:3;4100:9;4096:19;4079:37;:::i;:::-;4069:47;;3459:663;;;;;;;;:::o;4127:315::-;4195:6;4203;4256:2;4244:9;4235:7;4231:23;4227:32;4224:52;;;4272:1;4269;4262:12;4224:52;4311:9;4298:23;4330:31;4355:5;4330:31;:::i;:::-;4380:5;4432:2;4417:18;;;;4404:32;;-1:-1:-1;;;4127:315:1:o;4447:689::-;4542:6;4550;4558;4611:2;4599:9;4590:7;4586:23;4582:32;4579:52;;;4627:1;4624;4617:12;4579:52;4667:9;4654:23;-1:-1:-1;;;;;4737:2:1;4729:6;4726:14;4723:34;;;4753:1;4750;4743:12;4723:34;4791:6;4780:9;4776:22;4766:32;;4836:7;4829:4;4825:2;4821:13;4817:27;4807:55;;4858:1;4855;4848:12;4807:55;4898:2;4885:16;4924:2;4916:6;4913:14;4910:34;;;4940:1;4937;4930:12;4910:34;4995:7;4988:4;4978:6;4975:1;4971:14;4967:2;4963:23;4959:34;4956:47;4953:67;;;5016:1;5013;5006:12;4953:67;5047:4;5039:13;;;;5071:6;;-1:-1:-1;5109:20:1;;;;5096:34;;4447:689;-1:-1:-1;;;;4447:689:1:o;5141:241::-;5197:6;5250:2;5238:9;5229:7;5225:23;5221:32;5218:52;;;5266:1;5263;5256:12;5218:52;5305:9;5292:23;5324:28;5346:5;5324:28;:::i;5387:245::-;5454:6;5507:2;5495:9;5486:7;5482:23;5478:32;5475:52;;;5523:1;5520;5513:12;5475:52;5555:9;5549:16;5574:28;5596:5;5574:28;:::i;5637:245::-;5695:6;5748:2;5736:9;5727:7;5723:23;5719:32;5716:52;;;5764:1;5761;5754:12;5716:52;5803:9;5790:23;5822:30;5846:5;5822:30;:::i;5887:249::-;5956:6;6009:2;5997:9;5988:7;5984:23;5980:32;5977:52;;;6025:1;6022;6015:12;5977:52;6057:9;6051:16;6076:30;6100:5;6076:30;:::i;6141:280::-;6240:6;6293:2;6281:9;6272:7;6268:23;6264:32;6261:52;;;6309:1;6306;6299:12;6261:52;6341:9;6335:16;6360:31;6385:5;6360:31;:::i;6426:450::-;6495:6;6548:2;6536:9;6527:7;6523:23;6519:32;6516:52;;;6564:1;6561;6554:12;6516:52;6604:9;6591:23;-1:-1:-1;;;;;6629:6:1;6626:30;6623:50;;;6669:1;6666;6659:12;6623:50;6692:22;;6745:4;6737:13;;6733:27;-1:-1:-1;6723:55:1;;6774:1;6771;6764:12;6723:55;6797:73;6862:7;6857:2;6844:16;6839:2;6835;6831:11;6797:73;:::i;6881:180::-;6940:6;6993:2;6981:9;6972:7;6968:23;6964:32;6961:52;;;7009:1;7006;6999:12;6961:52;-1:-1:-1;7032:23:1;;6881:180;-1:-1:-1;6881:180:1:o;7066:184::-;7136:6;7189:2;7177:9;7168:7;7164:23;7160:32;7157:52;;;7205:1;7202;7195:12;7157:52;-1:-1:-1;7228:16:1;;7066:184;-1:-1:-1;7066:184:1:o;7255:521::-;7336:6;7344;7352;7360;7413:3;7401:9;7392:7;7388:23;7384:33;7381:53;;;7430:1;7427;7420:12;7381:53;7466:9;7453:23;7443:33;;7526:2;7515:9;7511:18;7498:32;7539:31;7564:5;7539:31;:::i;:::-;7589:5;-1:-1:-1;7646:2:1;7631:18;;7618:32;7659:30;7618:32;7659:30;:::i;:::-;7708:7;-1:-1:-1;7734:36:1;7766:2;7751:18;;7734:36;:::i;:::-;7724:46;;7255:521;;;;;;;:::o;7781:248::-;7849:6;7857;7910:2;7898:9;7889:7;7885:23;7881:32;7878:52;;;7926:1;7923;7916:12;7878:52;-1:-1:-1;;7949:23:1;;;8019:2;8004:18;;;7991:32;;-1:-1:-1;7781:248:1:o;8034:182::-;8091:6;8144:2;8132:9;8123:7;8119:23;8115:32;8112:52;;;8160:1;8157;8150:12;8112:52;8183:27;8200:9;8183:27;:::i;8221:257::-;8262:3;8300:5;8294:12;8327:6;8322:3;8315:19;8343:63;8399:6;8392:4;8387:3;8383:14;8376:4;8369:5;8365:16;8343:63;:::i;:::-;8460:2;8439:15;-1:-1:-1;;8435:29:1;8426:39;;;;8467:4;8422:50;;8221:257;-1:-1:-1;;8221:257:1:o;8483:274::-;8612:3;8650:6;8644:13;8666:53;8712:6;8707:3;8700:4;8692:6;8688:17;8666:53;:::i;:::-;8735:16;;;;;8483:274;-1:-1:-1;;8483:274:1:o;8762:415::-;8919:3;8957:6;8951:13;8973:53;9019:6;9014:3;9007:4;8999:6;8995:17;8973:53;:::i;:::-;9095:2;9091:15;;;;-1:-1:-1;;9087:53:1;9048:16;;;;9073:68;;;9168:2;9157:14;;8762:415;-1:-1:-1;;8762:415:1:o;9182:470::-;9361:3;9399:6;9393:13;9415:53;9461:6;9456:3;9449:4;9441:6;9437:17;9415:53;:::i;:::-;9531:13;;9490:16;;;;9553:57;9531:13;9490:16;9587:4;9575:17;;9553:57;:::i;:::-;9626:20;;9182:470;-1:-1:-1;;;;9182:470:1:o;10262:431::-;-1:-1:-1;;;;;10519:15:1;;;10501:34;;10571:15;;10566:2;10551:18;;10544:43;10623:2;10618;10603:18;;10596:30;;;10444:4;;10643:44;;10668:18;;10660:6;10643:44;:::i;10698:488::-;-1:-1:-1;;;;;10967:15:1;;;10949:34;;11019:15;;11014:2;10999:18;;10992:43;11066:2;11051:18;;11044:34;;;11114:3;11109:2;11094:18;;11087:31;;;10892:4;;11135:45;;11160:19;;11152:6;11135:45;:::i;:::-;11127:53;10698:488;-1:-1:-1;;;;;;10698:488:1:o;11564:632::-;11735:2;11787:21;;;11857:13;;11760:18;;;11879:22;;;11706:4;;11735:2;11958:15;;;;11932:2;11917:18;;;11706:4;12001:169;12015:6;12012:1;12009:13;12001:169;;;12076:13;;12064:26;;12145:15;;;;12110:12;;;;12037:1;12030:9;12001:169;;;-1:-1:-1;12187:3:1;;11564:632;-1:-1:-1;;;;;;11564:632:1:o;14370:217::-;14517:2;14506:9;14499:21;14480:4;14537:44;14577:2;14566:9;14562:18;14554:6;14537:44;:::i;15884:414::-;16086:2;16068:21;;;16125:2;16105:18;;;16098:30;16164:34;16159:2;16144:18;;16137:62;-1:-1:-1;;;16230:2:1;16215:18;;16208:48;16288:3;16273:19;;15884:414::o;22597:413::-;22799:2;22781:21;;;22838:2;22818:18;;;22811:30;22877:34;22872:2;22857:18;;22850:62;-1:-1:-1;;;22943:2:1;22928:18;;22921:47;23000:3;22985:19;;22597:413::o;24709:224::-;24748:3;24776:6;24809:2;24806:1;24802:10;24839:2;24836:1;24832:10;24870:3;24866:2;24862:12;24857:3;24854:21;24851:47;;;24878:18;;:::i;24938:128::-;24978:3;25009:1;25005:6;25002:1;24999:13;24996:39;;;25015:18;;:::i;:::-;-1:-1:-1;25051:9:1;;24938:128::o;25071:120::-;25111:1;25137;25127:35;;25142:18;;:::i;:::-;-1:-1:-1;25176:9:1;;25071:120::o;25196:168::-;25236:7;25302:1;25298;25294:6;25290:14;25287:1;25284:21;25279:1;25272:9;25265:17;25261:45;25258:71;;;25309:18;;:::i;:::-;-1:-1:-1;25349:9:1;;25196:168::o;25369:125::-;25409:4;25437:1;25434;25431:8;25428:34;;;25442:18;;:::i;:::-;-1:-1:-1;25479:9:1;;25369:125::o;25499:258::-;25571:1;25581:113;25595:6;25592:1;25589:13;25581:113;;;25671:11;;;25665:18;25652:11;;;25645:39;25617:2;25610:10;25581:113;;;25712:6;25709:1;25706:13;25703:48;;;-1:-1:-1;;25747:1:1;25729:16;;25722:27;25499:258::o;25762:136::-;25801:3;25829:5;25819:39;;25838:18;;:::i;:::-;-1:-1:-1;;;25874:18:1;;25762:136::o;25903:380::-;25982:1;25978:12;;;;26025;;;26046:61;;26100:4;26092:6;26088:17;26078:27;;26046:61;26153:2;26145:6;26142:14;26122:18;26119:38;26116:161;;;26199:10;26194:3;26190:20;26187:1;26180:31;26234:4;26231:1;26224:15;26262:4;26259:1;26252:15;26288:135;26327:3;-1:-1:-1;;26348:17:1;;26345:43;;;26368:18;;:::i;:::-;-1:-1:-1;26415:1:1;26404:13;;26288:135::o;26428:112::-;26460:1;26486;26476:35;;26491:18;;:::i;:::-;-1:-1:-1;26525:9:1;;26428:112::o;26545:127::-;26606:10;26601:3;26597:20;26594:1;26587:31;26637:4;26634:1;26627:15;26661:4;26658:1;26651:15;26677:127;26738:10;26733:3;26729:20;26726:1;26719:31;26769:4;26766:1;26759:15;26793:4;26790:1;26783:15;26809:127;26870:10;26865:3;26861:20;26858:1;26851:31;26901:4;26898:1;26891:15;26925:4;26922:1;26915:15;26941:127;27002:10;26997:3;26993:20;26990:1;26983:31;27033:4;27030:1;27023:15;27057:4;27054:1;27047:15;27073:127;27134:10;27129:3;27125:20;27122:1;27115:31;27165:4;27162:1;27155:15;27189:4;27186:1;27179:15;27205:131;-1:-1:-1;;;;;27280:31:1;;27270:42;;27260:70;;27326:1;27323;27316:12;27341:118;27427:5;27420:13;27413:21;27406:5;27403:32;27393:60;;27449:1;27446;27439:12;27464:131;-1:-1:-1;;;;;;27538:32:1;;27528:43;;27518:71;;27585:1;27582;27575:12

Swarm Source

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