ETH Price: $2,554.45 (+4.77%)

Token

Mega Millions Gangstar Apes (MMGA)
 

Overview

Max Total Supply

516 MMGA

Holders

304

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
0 MMGA
0x31b0a7fc79b4669d92771b35d58b9a1aead52d10
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:
MegaMilionsGangstarApes

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

pragma solidity ^0.8.0;

/// @title IERC2981Royalties
/// @dev Interface for the ERC2981 - Token Royalty standard
interface IERC2981Royalties {
    /// @notice Called with the sale price to determine how much royalty
    //          is owed and to whom.
    /// @param _tokenId - the NFT asset queried for royalty information
    /// @param _value - the sale price of the NFT asset specified by _tokenId
    /// @return _receiver - address of who should be sent the royalty payment
    /// @return _royaltyAmount - the royalty payment amount for value sale price
    function royaltyInfo(uint256 _tokenId, uint256 _value)
        external
        view
        returns (address _receiver, uint256 _royaltyAmount);
}


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


pragma solidity ^0.8.0;

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

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

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

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


pragma solidity ^0.8.0;

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

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

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

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

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


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


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


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


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


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


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


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


pragma solidity ^0.8.0;



/// @dev This is a contract used to add ERC2981 support to ERC721 and 1155
abstract contract ERC2981Base is ERC165, IERC2981Royalties {
    struct RoyaltyInfo {
        address recipient;
        uint24 amount;
    }

    /// @inheritdoc	ERC165
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool)
    {
        return
            interfaceId == type(IERC2981Royalties).interfaceId ||
            super.supportsInterface(interfaceId);
    }
}


pragma solidity ^0.8.0;



/// @dev This is a contract used to add ERC2981 support to ERC721 and 1155
/// @dev This implementation has the same royalties for each and every tokens
abstract contract ERC2981ContractWideRoyalties is ERC2981Base {
    RoyaltyInfo private _royalties;

    /// @dev Sets token royalties
    /// @param recipient recipient of the royalties
    /// @param value percentage (using 2 decimals - 10000 = 100, 0 = 0)
    function _setRoyalties(address recipient, uint256 value) internal {
        require(value <= 10000, 'ERC2981Royalties: Too high');
        _royalties = RoyaltyInfo(recipient, uint24(value));
    }

    /// @inheritdoc	IERC2981Royalties
    function royaltyInfo(uint256, uint256 value)
        external
        view
        override
        returns (address receiver, uint256 royaltyAmount)
    {
        RoyaltyInfo memory royalties = _royalties;
        receiver = royalties.recipient;
        royaltyAmount = (value * royalties.amount) / 10000;
    }
}


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


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


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


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 {}
}


pragma solidity ^0.8.0;


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

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

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

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

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

        return super.tokenURI(tokenId);
    }

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

    /**
     * @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 override {
        super._burn(tokenId);

        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }
    }
}


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


pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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


pragma solidity ^0.8.0;



/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}


// OpenZeppelin Contracts v4.3.2 (finance/PaymentSplitter.sol)

pragma solidity ^0.8.0;




/**
 * @title PaymentSplitter
 * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
 * that the Ether will be split in this way, since it is handled transparently by the contract.
 *
 * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
 * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
 * an amount proportional to the percentage of total shares they were assigned.
 *
 * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
 * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
 * function.
 *
 * NOTE: This contract assumes that ERC20 tokens will behave similarly to native tokens (Ether). Rebasing tokens, and
 * tokens that apply fees during transfers, are likely to not be supported as expected. If in doubt, we encourage you
 * to run tests before sending real value to this contract.
 */
contract PaymentSplitter is Context {
    event PayeeAdded(address account, uint256 shares);
    event PaymentReleased(address to, uint256 amount);
    event ERC20PaymentReleased(IERC20 indexed token, address to, uint256 amount);
    event PaymentReceived(address from, uint256 amount);
    event Warning(string message);

    uint256 private _totalShares = 50000;
    uint256 private _totalReleased;

    mapping(address => uint256) private _shares;
    mapping(address => uint256) private _released;
    address[] private _payees;

    mapping(IERC20 => uint256) private _erc20TotalReleased;
    mapping(IERC20 => mapping(address => uint256)) private _erc20Released;

    /**
     * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
     * the matching position in the `shares` array.
     *
     * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
     * duplicates in `payees`.
     */
    constructor(address[] memory payees, uint256[] memory shares_) payable {
        require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch");
        require(payees.length > 0, "PaymentSplitter: no payees");

        for (uint256 i = 0; i < payees.length; i++) {
            _addPayee(payees[i], shares_[i]);
        }
    }

    /**
     * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
     * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
     * reliability of the events, and not the actual splitting of Ether.
     *
     * To learn more about this see the Solidity documentation for
     * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
     * functions].
     */
    receive() external payable virtual {
        emit PaymentReceived(_msgSender(), msg.value);
    }
    
    function addToReleased(uint256 amount) internal {
        _totalReleased += amount;
    }

    /**
     * @dev Getter for the total shares held by payees.
     */
    function totalShares() public view returns (uint256) {
        return _totalShares;
    }

    /**
     * @dev Getter for the total amount of Ether already released.
     */
    function totalReleased() public view returns (uint256) {
        return _totalReleased;
    }

    /**
     * @dev Getter for the total amount of `token` already released. `token` should be the address of an IERC20
     * contract.
     */
    function totalReleased(IERC20 token) public view returns (uint256) {
        return _erc20TotalReleased[token];
    }

    /**
     * @dev Getter for the amount of shares held by an account.
     */
    function shares(address account) public view returns (uint256) {
        return _shares[account];
    }

    /**
     * @dev Getter for the amount of Ether already released to a payee.
     */
    function released(address account) public view returns (uint256) {
        return _released[account];
    }

    /**
     * @dev Getter for the amount of `token` tokens already released to a payee. `token` should be the address of an
     * IERC20 contract.
     */
    function released(IERC20 token, address account) public view returns (uint256) {
        return _erc20Released[token][account];
    }

    /**
     * @dev Getter for the address of the payee number `index`.
     */
    function payee(uint256 index) public view returns (address) {
        return _payees[index];
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
     * total shares and their previous withdrawals.
     */
    function release(address payable account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 totalReceived = address(this).balance + totalReleased();
        uint256 payment = _pendingPayment(account, totalReceived, released(account));

        if (payment != 0) {
            _released[account] += payment;
            _totalReleased += payment;

            Address.sendValue(account, payment);
            emit PaymentReleased(account, payment);
        } else {
            emit Warning("PaymentSplitter: account is not due payment");
        }
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their
     * percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20
     * contract.
     */
    function release(IERC20 token, address account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token);
        uint256 payment = _pendingPayment(account, totalReceived, released(token, account));

        if (payment != 0) {
            _erc20Released[token][account] += payment;
            _erc20TotalReleased[token] += payment;

            SafeERC20.safeTransfer(token, account, payment);
            emit ERC20PaymentReleased(token, account, payment);
        } else {
            emit Warning("PaymentSplitter: account is not due payment");
        }
    }

    /**
     * @dev internal logic for computing the pending payment of an `account` given the token historical balances and
     * already released amounts.
     */
    function _pendingPayment(
        address account,
        uint256 totalReceived,
        uint256 alreadyReleased
    ) private view returns (uint256) {
        return (totalReceived * _shares[account]) / _totalShares - alreadyReleased;
    }

    /**
     * @dev Add a new payee to the contract.
     * @param account The address of the payee to add.
     * @param shares_ The number of shares owned by the payee.
     */
    function _addPayee(address account, uint256 shares_) private {
        require(account != address(0), "PaymentSplitter: account is the zero address");
        require(shares_ > 0, "PaymentSplitter: shares are 0");
        require(_shares[account] == 0, "PaymentSplitter: account already has shares");

        _payees.push(account);
        _shares[account] = shares_;
        _totalShares = _totalShares + shares_;
        emit PayeeAdded(account, shares_);
    }
}

pragma solidity ^0.8.7;


contract MegaMilionsGangstarApes is ERC721, ERC721Enumerable, ERC721URIStorage, ERC2981ContractWideRoyalties, Ownable, PaymentSplitter {
    using Counters for Counters.Counter;
    using Strings for uint;
	using Math for uint;
	using SafeMath for uint;
    
    enum PriceType{ PROMO, FULL }   //{ 0, 1 }
    struct Promo {
        uint startTime;
        uint duration;
    }
    
    // Mappings
    mapping(address => bool) public whitelisted;
    mapping(address => uint) public promos;
    mapping(address => bool) public admins;
    
    // Default values
    uint internal constant MILLIETHER = 1e15; //0.001 ETHER = 1,000,000,000,000,000 WEI
    uint internal promoPrice = 0.1 ether;
    uint internal fullPrice = 0.3 ether;
    uint internal maxSupply = 10000;
    uint internal maxMint = 10;
    uint internal maxDiscountedMintPerUser = 2;
    
    // Vars
    string private baseURI;
    bool private paused = false;
    Promo private promo;
    
    // Wallet shares - 50% of revenues shared to team
	address private DP = 0xcd70Dc892F240D50b7D46CE120dc75c3243E72ab;
	address private RG = 0x39c34674EEC3AE5F1E9a6Ee899CB85f11a55D990;
	address private JH = 0xD484E2745d27FA62E6ab0396fd46e0A3E3A00eFc;
	address private LH = 0xB2CEe0977Bbb0446B358E0Cb3de69e10EdC5eDA3;
	address private EA = 0x3a4FF805cD9C063f06a0263EEa99F531FAa13B91;
	address private AG = 0x79f6E63B4D593F3794019A4FEFB52196C602E037;
	address private JP = 0xd7EE8aF7a902bb208878E50863220e2872b73992;
	address private MR = 0xaFBC38a36Cb173d75735f3f781e9133939e99888;
	address private AF = 0x7a2DD031a02Fd595C7BCb0A278A4518daB31AF8d;
	address private MA = 0xEe3642cb451F6f4ec5C6dd6699fFE69F2D07921E;
	
    uint[] private _shares = [
        675,
        675,
        11250,
        6750,
        9865,
        6750,
        7865,
        270,
        675,
        5225
    ];
    address[] private _team = [
        DP,
        RG,
        JH,
        LH,
        EA,
        AG,
        JP,
        MR,
        AF,
        MA
    ];
    
    // Game
    struct RoadmapStep { 
        uint64 supply;
        uint64 winnersCount;
        uint64 prizeValue;
        uint64 winnersToDraw;
    }
    uint private drawIndex = 0;
    RoadmapStep[9] private roadmap;
    mapping(uint => bool) internal isPrizeGiven;
    
    // Modifiers
    modifier onlyAdmin() {
        require(address(this) == _msgSender() || owner() == _msgSender() || admins[msg.sender], "Not admin");
        _;
    }
    
    // Emitters
    event BaseURIChanged(string tokenBaseURI);
    event TicketPriceChanged(PriceType priceType, uint price);
    event MaxMintAmountChanged(uint amount);
    event MaxDiscountedMintPerUser(uint mintPerUser);
    event Paused(bool paused);
    event PromoChanged(uint startTime, uint duration);
    event Airdropped(address to, uint tokenId);
    event Winner(uint token, address winner, uint value);
    event Log(string error);

    constructor()
        ERC721("Mega Millions Gangstar Apes", "MMGA")
        PaymentSplitter(_team, _shares)
    {
        //set default admins
        admins[DP] = true;
        admins[RG] = true;
        
        initRoadmap();
        
        //if ERC2981 supported
        _setRoyalties(address(this), 1000);  //10%
    }
    
    // ***************************
    //  Overrides
    // ***************************
    function _beforeTokenTransfer(address from, address to, uint tokenId)
        internal
        override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable, ERC2981Base)
        returns (bool) {
        return super.supportsInterface(interfaceId);
    }
    
    function _burn(uint _tokenId) 
        internal
        override(ERC721, ERC721URIStorage) {
        super._burn(_tokenId);
    }
    
    function burn(uint _tokenId) external onlyAdmin {
        _burn(_tokenId);
        maxSupply = maxSupply - 1;
    }

    // ***************************
    //  Admins management by owner
    // ***************************
    function enableAdmin(address addr) external onlyOwner {
        admins[addr] = true;
    }

    function disableAdmin(address addr) external onlyOwner {
        require(addr != owner(), "Can't disable owner");
        admins[addr] = false;
    }
    
    // ***************************
    //  Release & withdraw
    // ***************************
    function releaseAll() public onlyAdmin {
        for (uint i = 0; i < _team.length; i++) {
            address member = _team[i];
            try this.release(payable(member)) {}
            catch Error(string memory revertReason) {
                emit Log(revertReason);
            } catch (bytes memory returnData) {
                emit Log(string(returnData));
            }
        }
    }
    
    function withdraw() external onlyAdmin {
        releaseAll();
        pay(payable(owner()), address(this).balance);
    }
    
    // ***************************
    //  Contract management
    // ***************************
    function pause(bool newState) external onlyAdmin {
        paused = newState;
        emit Paused(newState);
    }
 
    function addWhitelistedUsers(address[] calldata users) external onlyAdmin {
        for (uint i = 0; i < users.length; i++) {
            require(users[i] != address(0), "Can't add a zero address");
            if (whitelisted[users[i]] == false) {
                whitelisted[users[i]] = true;
            }
        }
    }
 
    function removeWhitelistedUsers(address[] calldata users) external onlyAdmin {
        for (uint i = 0; i < users.length; i++) {
            require(users[i] != address(0), "Can't remove a zero address");
            if (whitelisted[users[i]] == true) {
                whitelisted[users[i]] = false;
            }
        }
    }
    // Duration in seconds
    function startPromo(uint duration) external onlyAdmin {
        uint startTime = block.timestamp;
        promo = Promo(startTime, duration);
        emit PromoChanged(startTime, duration);
    }

    // ***************************
    //  URI management (Reveal)
    // ***************************
    function _baseURI() internal view virtual override returns (string memory) {
        return baseURI;
    }
    
    function setBaseURI(string memory newBaseURI) external onlyAdmin {
        baseURI = newBaseURI;
        emit BaseURIChanged(newBaseURI);
    }

    function setTokenURI(uint _tokenId, string memory _tokenURI) external onlyAdmin {
        require(_exists(_tokenId), "URI set of nonexistent token");
        _setTokenURI(_tokenId, _tokenURI);
    }
    
    function tokenURI(uint _tokenId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (string memory) {
        return super.tokenURI(_tokenId);
    }

    // ***************************
    //  Promo & price management
    // ***************************
    function setPrice(PriceType priceType, uint price) external onlyAdmin {
        require(price > 0, "Zero price");
        if (priceType == PriceType.PROMO) {
            promoPrice = price;
        } else if (priceType == PriceType.FULL) {
            fullPrice = price;
        }
        emit TicketPriceChanged(priceType, price);
    }
    
    function setMaxMintAmount(uint amount) external onlyAdmin {
        maxMint = amount;
        emit MaxMintAmountChanged(amount);
    }
    
    function setMaxDiscountedMintPerUser(uint mintPerUser) external onlyAdmin {
        maxDiscountedMintPerUser = mintPerUser;
        emit MaxDiscountedMintPerUser(mintPerUser);
    }
    
    function isPromo() public view returns (bool) {
        return (promo.startTime > 0 &&
                block.timestamp >= promo.startTime &&
                block.timestamp <= (promo.startTime + promo.duration));
    }
    
    // Dynamically gets the token price according to promo, whitelist and msg.sender
    function getPrice() public view returns (uint) {
        uint price = fullPrice;
        if (admins[msg.sender] == true) {
			price = 0;
		} else if ((isPromo() || whitelisted[msg.sender] == true) &&
            promos[msg.sender] < maxDiscountedMintPerUser)
        {
            price = promoPrice;
        }
        return price;
    }
    
    // ***************************
    //  Mint, Gift & Airdrop
    // ***************************
    function mint(address to, uint amount) external payable {
        uint supply = totalSupply();
        bool discounted = (getPrice() == promoPrice);
        require(!paused, "Contract is paused");
        require(amount > 0, "Amount is zero");
        require(amount <= maxMint, "Amount exceeds max mint");
        require(supply + amount <= maxSupply, "Max supply reached");
        if (admins[msg.sender] != true) {
            if (discounted) {
                require(promos[to] + amount <= maxDiscountedMintPerUser, "Max discounted NFT exceeded for this user");
            }
            require(getPrice().mul(amount) == msg.value, "Ether value sent is not correct");
        }
        for (uint i = 1; i <= amount; i++) {
            _safeMint(to, supply + i);
            if(discounted) {
                promos[to] = promos[to] + 1;
            }
        }
    }
    
    function gift(address to, uint amount) external onlyAdmin {
        uint supply = totalSupply();
        require(!paused, "Contract is paused");
        require(amount > 0, "Amount is zero");
        require(amount <= maxMint, "Amount exceeds max mint");
        require(supply + amount <= maxSupply, "Max supply reached");
        for (uint i = 1; i <= amount; i++) {
            _safeMint(to, supply + i);
        }
    }
    
    function airdrop(address to, uint tokenId) external onlyAdmin {
        require(!paused, "Contract is paused");
        require(to != address(0), "Can't airdrop to a zero address");
        safeTransferFrom(msg.sender, to, tokenId);
        emit Airdropped(to, tokenId);
    }
    
    
    // ***************************
    //  Game management
    // ***************************
    
    // Main function to draw the roadmap prizes and pay the winners
    function draw() external payable onlyAdmin {
        require(!paused, "Contract is paused");
        releaseAll();
        uint[] memory prizes = consumeRoadmapPrizes(totalSupply());
        uint nonce = block.difficulty;
        for (uint i = 0; i < prizes.length; i++) {
            uint tokenId = randToken(i, nonce);
            require(tokenId != 0, "Incorrect tokenId");
            address winner = ownerOf(tokenId);
            require(winner != address(0), "Can't pay a zero address");
            pay(payable(winner), (prizes[i] * MILLIETHER));
            nonce=nonce^uint(keccak256(abi.encodePacked(winner)));
            emit Winner(tokenId, winner, prizes[i]);
        }
    }
    
    // Alternative draw method to choose one random winner with a given prize
    function drawOne(uint milliEther) external payable onlyAdmin {
        require(!paused, "Contract is paused");
        releaseAll();
        uint seed = uint(keccak256(abi.encodePacked(block.coinbase)));
        uint nonce = uint(keccak256(abi.encodePacked(msg.sender)));
        uint tokenId = randToken(seed, nonce);
        require(tokenId != 0, "Incorrect tokenId");
        address winner = ownerOf(tokenId);
        require(winner != address(0), "Can't pay a zero address");
        pay(payable(winner), (milliEther * MILLIETHER));
        emit Winner(tokenId, winner, milliEther);
    }
    
    // ***************************
    //  Internals
    // ***************************
    
    // Initialize the roadmap
    function initRoadmap() internal onlyAdmin {
        roadmap[0] = RoadmapStep(1000,2,22000,1);
        roadmap[1] = RoadmapStep(2000,3,22000,1);
        roadmap[2] = RoadmapStep(3000,1,44000,1);
        roadmap[3] = RoadmapStep(4000,1,44000,1);
        roadmap[4] = RoadmapStep(5000,50,1100,2);
        roadmap[5] = RoadmapStep(7000,50,1100,2);
        roadmap[6] = RoadmapStep(7000,10,11000,1);
        roadmap[7] = RoadmapStep(10000,1,220000,1);
        roadmap[8] = RoadmapStep(10000,50,2200,1);
    }
    
    // Consume some prizes according to the roadmap
    // Rule : winnersCount per week and only one prizeValue same amount at a time.
    function consumeRoadmapPrizes(uint supply) internal onlyAdmin returns (uint[] memory) {    
        uint index = 0;
        uint[] memory temp = new uint[](16);
        for (uint i = 0; i < 9; i++) {
            isPrizeGiven[roadmap[i].prizeValue] = false;
        }
        for (uint i = 0; i < roadmap.length; i++) {
            if (roadmap[i].supply > supply) {
                break;
            }
            if ((roadmap[i].supply <= supply) &&
                (roadmap[i].winnersCount > 0) &&
                !isPrizeGiven[roadmap[i].prizeValue]) {
                for (uint j = 0; j < Math.min(roadmap[i].winnersToDraw, roadmap[i].winnersCount); j++) {
                    roadmap[i].winnersCount--;
                    temp[index] = roadmap[i].prizeValue;
                    index++;
                }
                isPrizeGiven[roadmap[i].prizeValue] = true;
            }
        }
        uint[] memory prizes = new uint[](index);
        for (uint i = 0; i < index; i++) {
            prizes[i] = temp[i];
        }
        return prizes;
    }

    // Randomly picks a tokenId
    function randToken(uint seed, uint nonce) internal view onlyAdmin returns(uint) {
        uint supply = totalSupply();
        if (supply > 0) {
            uint tokenId = randModulus(supply, seed, nonce);
            if (tokenId > 0) {
                return tokenId;
            }
        }
        return 0;
    }
    
    // Pays eth amount to an address
    function pay(address payable to, uint amount) internal onlyAdmin {
        require(to != address(0), "Can't pay a zero address");
        require(address(this).balance >= amount, "No sufficient fund in contract to pay the address");
        (bool sent, bytes memory data) = to.call{value: amount}("");
        if (sent) {
            addToReleased(amount);
        }
        require(sent, string(abi.encodePacked("Failed to send Ether:", data)));
    } 
    
    // Gets a random number
    function randModulus(uint max, uint seed, uint nonce) internal view returns(uint) {
        uint blockNumber = block.number-1;
        if (block.number>(seed % 256)) {
            blockNumber=block.number-(seed % 256);
        }
        uint rand = uint(keccak256(abi.encodePacked(
            seed^block.timestamp,
            block.timestamp, 
            msg.data,
            nonce, 
            msg.sender,
            blockhash(blockNumber)
            )
        )) % max;
        return rand+1;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Airdropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"tokenBaseURI","type":"string"}],"name":"BaseURIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20PaymentReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"error","type":"string"}],"name":"Log","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"mintPerUser","type":"uint256"}],"name":"MaxDiscountedMintPerUser","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MaxMintAmountChanged","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":"bool","name":"paused","type":"bool"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"PayeeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"PromoChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum MegaMilionsGangstarApes.PriceType","name":"priceType","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"TicketPriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"message","type":"string"}],"name":"Warning","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"token","type":"uint256"},{"indexed":false,"internalType":"address","name":"winner","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Winner","type":"event"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"}],"name":"addWhitelistedUsers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"admins","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"disableAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"draw","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"milliEther","type":"uint256"}],"name":"drawOne","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"enableAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"gift","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPromo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"newState","type":"bool"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"payee","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"promos","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"account","type":"address"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"releaseAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"released","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"released","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"}],"name":"removeWhitelistedUsers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"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":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mintPerUser","type":"uint256"}],"name":"setMaxDiscountedMintPerUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setMaxMintAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum MegaMilionsGangstarApes.PriceType","name":"priceType","type":"uint8"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"string","name":"_tokenURI","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"shares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"startPromo","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":"contract IERC20","name":"token","type":"address"}],"name":"totalReleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","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":[{"internalType":"address","name":"","type":"address"}],"name":"whitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

61c350600d5567016345785d8a0000601755670429d069189e0000601855612710601955600a601a8190556002601b55601d805460ff19169055602080546001600160a01b031990811673cd70dc892f240d50b7d46ce120dc75c3243e72ab179091556021805482167339c34674eec3ae5f1e9a6ee899cb85f11a55d99017905560228054821673d484e2745d27fa62e6ab0396fd46e0a3e3a00efc17905560238054821673b2cee0977bbb0446b358e0cb3de69e10edc5eda3179055602480548216733a4ff805cd9c063f06a0263eea99f531faa13b911790556025805482167379f6e63b4d593f3794019a4fefb52196c602e03717905560268054821673d7ee8af7a902bb208878e50863220e2872b7399217905560278054821673afbc38a36cb173d75735f3f781e9133939e99888179055602880548216737a2dd031a02fd595c7bcb0a278a4518dab31af8d1790556029805490911673ee3642cb451f6f4ec5c6dd6699ffe69f2d07921e1790556101c06040526102a3608081815260a0829052612bf260c052611a5e60e08190526126896101005261012052611eb96101405261010e61016052610180919091526114696101a052620001c891602a919062000ac0565b506040805161014081018252602080546001600160a01b0390811683526021548116918301919091526022548116928201929092526023548216606082015260245482166080820152602554821660a0820152602654821660c0820152602754821660e082015260285482166101008201526029549091166101208201526200025690602b90600a62000b16565b506000602c553480156200026957600080fd5b50602b805480602002602001604051908101604052809291908181526020018280548015620002c257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311620002a3575b5050505050602a8054806020026020016040519081016040528092919081815260200182805480156200031557602002820191906000526020600020905b81548152602001906001019080831162000300575b5050604080518082018252601b81527f4d656761204d696c6c696f6e732047616e6773746172204170657300000000006020808301918252835180850190945260048452634d4d474160e01b9084015281519195509193506200037d92506000919062000b6e565b5080516200039390600190602084019062000b6e565b505050620003b0620003aa6200054360201b60201c565b62000547565b8051825114620004225760405162461bcd60e51b815260206004820152603260248201527f5061796d656e7453706c69747465723a2070617965657320616e6420736861726044820152710cae640d8cadccee8d040dad2e6dac2e8c6d60731b60648201526084015b60405180910390fd5b6000825111620004755760405162461bcd60e51b815260206004820152601a60248201527f5061796d656e7453706c69747465723a206e6f20706179656573000000000000604482015260640162000419565b60005b8251811015620004e157620004cc8382815181106200049b576200049b62000c8e565b6020026020010151838381518110620004b857620004b862000c8e565b60200260200101516200059960201b60201c565b80620004d88162000c5a565b91505062000478565b5050602080546001600160a01b039081166000908152601690925260408083208054600160ff1991821681179092556021549093168452922080549091169091179055506200052f62000787565b6200053d306103e862000a22565b62000ca4565b3390565b600c80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216620006065760405162461bcd60e51b815260206004820152602c60248201527f5061796d656e7453706c69747465723a206163636f756e74206973207468652060448201526b7a65726f206164647265737360a01b606482015260840162000419565b60008111620006585760405162461bcd60e51b815260206004820152601d60248201527f5061796d656e7453706c69747465723a20736861726573206172652030000000604482015260640162000419565b6001600160a01b0382166000908152600f602052604090205415620006d45760405162461bcd60e51b815260206004820152602b60248201527f5061796d656e7453706c69747465723a206163636f756e7420616c726561647960448201526a206861732073686172657360a81b606482015260840162000419565b60118054600181019091557f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c680180546001600160a01b0319166001600160a01b0384169081179091556000908152600f60205260409020819055600d546200073e90829062000c02565b600d55604080516001600160a01b0384168152602081018390527f40c340f65e17194d14ddddb073d3c9f888e3cb52b5aae0c6c7706b4fbc905fac910160405180910390a15050565b30331480620007a05750600c546001600160a01b031633145b80620007bb57503360009081526016602052604090205460ff165b620007f55760405162461bcd60e51b81526020600482015260096024820152682737ba1030b236b4b760b91b604482015260640162000419565b60408051608080820183526103e88252600260208084018290526155f084860181905260016060958601819052780100000000000055f0000000000000000200000000000003e8602d55865180860188526107d0815260038185015280880192909252908501819052780100000000000055f0000000000000000300000000000007d0602e5585518085018752610bb8815280830182905261abe08188018190529086018290527801000000000000abe000000000000000010000000000000bb8602f5586518086018852610fa081528084018390528088019190915285018190527801000000000000abe000000000000000010000000000000fa0603055855180850187526113888152603281840181905261044c8289018190529187018590527802000000000000044c0000000000000032000000000000138860315587518087018952611b58808252818601839052818a01939093528701949094527802000000000000044c00000000000000320000000000001b58845586518086018852908152600a81840152612af881880152850181905278010000000000002af8000000000000000a0000000000001b586033558551808501875261271080825281840183905262035b608289015290860182905278010000000000035b6000000000000000010000000000002710603455865194850187528452908301919091526108989382019390935201527801000000000000089800000000000000320000000000002710603555565b61271081111562000a765760405162461bcd60e51b815260206004820152601a60248201527f45524332393831526f79616c746965733a20546f6f2068696768000000000000604482015260640162000419565b604080518082019091526001600160a01b0390921680835262ffffff9091166020909201829052600b8054600160a01b9093026001600160b81b0319909316909117919091179055565b82805482825590600052602060002090810192821562000b04579160200282015b8281111562000b04578251829061ffff1690559160200191906001019062000ae1565b5062000b1292915062000beb565b5090565b82805482825590600052602060002090810192821562000b04579160200282015b8281111562000b0457825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000b37565b82805462000b7c9062000c1d565b90600052602060002090601f01602090048101928262000ba0576000855562000b04565b82601f1062000bbb57805160ff191683800117855562000b04565b8280016001018555821562000b04579182015b8281111562000b0457825182559160200191906001019062000bce565b5b8082111562000b12576000815560010162000bec565b6000821982111562000c185762000c1862000c78565b500190565b600181811c9082168062000c3257607f821691505b6020821081141562000c5457634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141562000c715762000c7162000c78565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b614d188062000cb46000396000f3fe60806040526004361061031e5760003560e01c80636352211e116101ab578063a22cb465116100f7578063d79779b211610095578063e985e9c51161006f578063e985e9c5146109e4578063eff42f2e14610a2d578063f2fde38b14610a4d578063f5d94f6a14610a6d57600080fd5b8063d79779b214610969578063d936547e1461099f578063e33b7de3146109cf57600080fd5b8063bea532ff116100d1578063bea532ff146108d3578063c87b56dd146108f3578063cbce4c9714610913578063ce7c2ac21461093357600080fd5b8063a22cb46514610866578063b134a06714610886578063b88d4fde146108b357600080fd5b806389b1f38e116101645780638da5cb5b1161013e5780638da5cb5b146107e857806395d89b41146108065780639852595c1461081b57806398d5fdca1461085157600080fd5b806389b1f38e146107935780638b83209b146107a85780638ba4cc3c146107c857600080fd5b80636352211e146106de5780636496d3fc146106fe5780636a00670b1461071e57806370a082311461073e578063715018a61461075e578063751e9a9c1461077357600080fd5b80633a98ef391161026a578063429b62e5116102235780634f6ccce7116101fd5780634f6ccce71461066957806355f804b3146106895780635be7fde8146106a95780635f19d2fc146106be57600080fd5b8063429b62e514610606578063431d729f1461063657806348b750441461064957600080fd5b80633a98ef39146105435780633ccfd60b14610558578063406072a91461056d57806340c10f19146105b357806342842e0e146105c657806342966c68146105e657600080fd5b80630eecae21116102d757806319165587116102b157806319165587146104a457806323b872dd146104c45780632a55205a146104e45780632f745c591461052357600080fd5b80630eecae211461045d578063162094c41461046557806318160ddd1461048557600080fd5b806301ffc9a71461036c57806302329a29146103a157806306fdde03146103c3578063081812fc146103e5578063088a4ed01461041d578063095ea7b31461043d57600080fd5b36610367577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be77033604080516001600160a01b0390921682523460208301520160405180910390a1005b600080fd5b34801561037857600080fd5b5061038c6103873660046145c7565b610a8d565b60405190151581526020015b60405180910390f35b3480156103ad57600080fd5b506103c16103bc36600461458d565b610a9e565b005b3480156103cf57600080fd5b506103d8610b3d565b6040516103989190614837565b3480156103f157600080fd5b50610405610400366004614657565b610bcf565b6040516001600160a01b039091168152602001610398565b34801561042957600080fd5b506103c1610438366004614657565b610c57565b34801561044957600080fd5b506103c16104583660046144ed565b610cda565b6103c1610df0565b34801561047157600080fd5b506103c1610480366004614689565b610ffc565b34801561049157600080fd5b506008545b604051908152602001610398565b3480156104b057600080fd5b506103c16104bf3660046143a9565b6110ad565b3480156104d057600080fd5b506103c16104df3660046143ff565b6111f2565b3480156104f057600080fd5b506105046104ff3660046146c5565b611223565b604080516001600160a01b039093168352602083019190915201610398565b34801561052f57600080fd5b5061049661053e3660046144ed565b611278565b34801561054f57600080fd5b50600d54610496565b34801561056457600080fd5b506103c161130e565b34801561057957600080fd5b506104966105883660046143c6565b6001600160a01b03918216600090815260136020908152604080832093909416825291909152205490565b6103c16105c13660046144ed565b611381565b3480156105d257600080fd5b506103c16105e13660046143ff565b611622565b3480156105f257600080fd5b506103c1610601366004614657565b61163d565b34801561061257600080fd5b5061038c6106213660046143a9565b60166020526000908152604090205460ff1681565b6103c1610644366004614657565b6116a9565b34801561065557600080fd5b506103c16106643660046143c6565b611860565b34801561067557600080fd5b50610496610684366004614657565b611a6c565b34801561069557600080fd5b506103c16106a4366004614623565b611aff565b3480156106b557600080fd5b506103c1611b90565b3480156106ca57600080fd5b506103c16106d9366004614657565b611d43565b3480156106ea57600080fd5b506104056106f9366004614657565b611dc6565b34801561070a57600080fd5b506103c1610719366004614519565b611e3d565b34801561072a57600080fd5b506103c1610739366004614601565b611fca565b34801561074a57600080fd5b506104966107593660046143a9565b6120d6565b34801561076a57600080fd5b506103c161215d565b34801561077f57600080fd5b506103c161078e3660046143a9565b612191565b34801561079f57600080fd5b5061038c612230565b3480156107b457600080fd5b506104056107c3366004614657565b612266565b3480156107d457600080fd5b506103c16107e33660046144ed565b612296565b3480156107f457600080fd5b50600c546001600160a01b0316610405565b34801561081257600080fd5b506103d86123a7565b34801561082757600080fd5b506104966108363660046143a9565b6001600160a01b031660009081526010602052604090205490565b34801561085d57600080fd5b506104966123b6565b34801561087257600080fd5b506103c16108813660046144bf565b612433565b34801561089257600080fd5b506104966108a13660046143a9565b60156020526000908152604090205481565b3480156108bf57600080fd5b506103c16108ce366004614440565b6124f8565b3480156108df57600080fd5b506103c16108ee3660046143a9565b61252a565b3480156108ff57600080fd5b506103d861090e366004614657565b612578565b34801561091f57600080fd5b506103c161092e3660046144ed565b612583565b34801561093f57600080fd5b5061049661094e3660046143a9565b6001600160a01b03166000908152600f602052604090205490565b34801561097557600080fd5b506104966109843660046143a9565b6001600160a01b031660009081526012602052604090205490565b3480156109ab57600080fd5b5061038c6109ba3660046143a9565b60146020526000908152604090205460ff1681565b3480156109db57600080fd5b50600e54610496565b3480156109f057600080fd5b5061038c6109ff3660046143c6565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b348015610a3957600080fd5b506103c1610a48366004614519565b612709565b348015610a5957600080fd5b506103c1610a683660046143a9565b61289c565b348015610a7957600080fd5b506103c1610a88366004614657565b612934565b6000610a98826129d5565b92915050565b30331480610ab65750600c546001600160a01b031633145b80610ad057503360009081526016602052604090205460ff165b610af55760405162461bcd60e51b8152600401610aec90614a16565b60405180910390fd5b601d805460ff19168215159081179091556040519081527f0e2fb031ee032dc02d8011dc50b816eb450cf856abd8261680dac74f72165bd2906020015b60405180910390a150565b606060008054610b4c90614aea565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7890614aea565b8015610bc55780601f10610b9a57610100808354040283529160200191610bc5565b820191906000526020600020905b815481529060010190602001808311610ba857829003601f168201915b5050505050905090565b6000610bda826129fa565b610c3b5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610aec565b506000908152600460205260409020546001600160a01b031690565b30331480610c6f5750600c546001600160a01b031633145b80610c8957503360009081526016602052604090205460ff165b610ca55760405162461bcd60e51b8152600401610aec90614a16565b601a8190556040518181527f71ef44637f994911a9fa6bc89bc19c9bbf6f510a992e74f90880ffbccd7b2c6b90602001610b32565b6000610ce582611dc6565b9050806001600160a01b0316836001600160a01b03161415610d535760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610aec565b336001600160a01b0382161480610d6f5750610d6f81336109ff565b610de15760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610aec565b610deb8383612a17565b505050565b30331480610e085750600c546001600160a01b031633145b80610e2257503360009081526016602052604090205460ff165b610e3e5760405162461bcd60e51b8152600401610aec90614a16565b601d5460ff1615610e615760405162461bcd60e51b8152600401610aec906149b3565b610e69611b90565b6000610e7c610e7760085490565b612a85565b90504460005b8251811015610deb576000610e978284612e53565b905080610eda5760405162461bcd60e51b8152602060048201526011602482015270125b98dbdc9c9958dd081d1bdad95b9259607a1b6044820152606401610aec565b6000610ee582611dc6565b90506001600160a01b038116610f0d5760405162461bcd60e51b8152600401610aec906149df565b610f428166038d7ea4c68000878681518110610f2b57610f2b614bd8565b6020026020010151610f3d9190614a65565b612ee0565b6040516001600160601b0319606083901b1660208201526034016040516020818303038152906040528051906020012060001c841893507f1c2ae1f7e99dbbbfe25aac964f3889ea68259d88b74709f53037a6fb930bb02a8282878681518110610fae57610fae614bd8565b6020026020010151604051610fdf939291909283526001600160a01b03919091166020830152604082015260600190565b60405180910390a150508080610ff490614b51565b915050610e82565b303314806110145750600c546001600160a01b031633145b8061102e57503360009081526016602052604090205460ff165b61104a5760405162461bcd60e51b8152600401610aec90614a16565b611053826129fa565b61109f5760405162461bcd60e51b815260206004820152601c60248201527f55524920736574206f66206e6f6e6578697374656e7420746f6b656e000000006044820152606401610aec565b6110a98282613064565b5050565b6001600160a01b0381166000908152600f60205260409020546110e25760405162461bcd60e51b8152600401610aec9061489c565b60006110ed600e5490565b6110f79047614a39565b90506000611124838361111f866001600160a01b031660009081526010602052604090205490565b6130ef565b905080156111c5576001600160a01b03831660009081526010602052604081208054839290611154908490614a39565b9250508190555080600e600082825461116d9190614a39565b9091555061117d90508382613137565b604080516001600160a01b0385168152602081018390527fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b05691015b60405180910390a1505050565b7f8e21091fbff1b481f4a0383146b43469a9f1bfc97275d232206e61929bf9541a6040516111b8906148e2565b6111fc3382613250565b6112185760405162461bcd60e51b8152600401610aec90614962565b610deb83838361333a565b60408051808201909152600b546001600160a01b038116808352600160a01b90910462ffffff16602083018190529091600091612710906112649086614a65565b61126e9190614a51565b9150509250929050565b6000611283836120d6565b82106112e55760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610aec565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b303314806113265750600c546001600160a01b031633145b8061134057503360009081526016602052604090205460ff165b61135c5760405162461bcd60e51b8152600401610aec90614a16565b611364611b90565b61137f611379600c546001600160a01b031690565b47612ee0565b565b600061138c60085490565b9050600060175461139b6123b6565b601d549114915060ff16156113c25760405162461bcd60e51b8152600401610aec906149b3565b600083116114035760405162461bcd60e51b815260206004820152600e60248201526d416d6f756e74206973207a65726f60901b6044820152606401610aec565b601a5483111561144f5760405162461bcd60e51b8152602060048201526017602482015276105b5bdd5b9d08195e18d959591cc81b585e081b5a5b9d604a1b6044820152606401610aec565b60195461145c8484614a39565b111561149f5760405162461bcd60e51b815260206004820152601260248201527113585e081cdd5c1c1b1e481c995858da195960721b6044820152606401610aec565b3360009081526016602052604090205460ff1615156001146115a857801561154857601b546001600160a01b0385166000908152601560205260409020546114e8908590614a39565b11156115485760405162461bcd60e51b815260206004820152602960248201527f4d617820646973636f756e746564204e465420657863656564656420666f72206044820152683a3434b9903ab9b2b960b91b6064820152608401610aec565b3461155b846115556123b6565b906134e5565b146115a85760405162461bcd60e51b815260206004820152601f60248201527f45746865722076616c75652073656e74206973206e6f7420636f7272656374006044820152606401610aec565b60015b83811161161b576115c5856115c08386614a39565b6134f1565b8115611609576001600160a01b0385166000908152601560205260409020546115ef906001614a39565b6001600160a01b0386166000908152601560205260409020555b8061161381614b51565b9150506115ab565b5050505050565b610deb838383604051806020016040528060008152506124f8565b303314806116555750600c546001600160a01b031633145b8061166f57503360009081526016602052604090205460ff165b61168b5760405162461bcd60e51b8152600401610aec90614a16565b6116948161350b565b60016019546116a39190614a84565b60195550565b303314806116c15750600c546001600160a01b031633145b806116db57503360009081526016602052604090205460ff165b6116f75760405162461bcd60e51b8152600401610aec90614a16565b601d5460ff161561171a5760405162461bcd60e51b8152600401610aec906149b3565b611722611b90565b604080516001600160601b031941606090811b8216602080850191909152845180850360140181526034850186528051908201203390921b9092166054840152835180840360480181526068909301909352815191012060006117858383612e53565b9050806117c85760405162461bcd60e51b8152602060048201526011602482015270125b98dbdc9c9958dd081d1bdad95b9259607a1b6044820152606401610aec565b60006117d382611dc6565b90506001600160a01b0381166117fb5760405162461bcd60e51b8152600401610aec906149df565b61181081610f3d66038d7ea4c6800088614a65565b604080518381526001600160a01b03831660208201529081018690527f1c2ae1f7e99dbbbfe25aac964f3889ea68259d88b74709f53037a6fb930bb02a9060600160405180910390a15050505050565b6001600160a01b0381166000908152600f60205260409020546118955760405162461bcd60e51b8152600401610aec9061489c565b6001600160a01b0382166000908152601260205260408120546040516370a0823160e01b81523060048201526001600160a01b038516906370a082319060240160206040518083038186803b1580156118ed57600080fd5b505afa158015611901573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119259190614670565b61192f9190614a39565b90506000611968838361111f87876001600160a01b03918216600090815260136020908152604080832093909416825291909152205490565b90508015611a30576001600160a01b038085166000908152601360209081526040808320938716835292905290812080548392906119a7908490614a39565b90915550506001600160a01b038416600090815260126020526040812080548392906119d4908490614a39565b909155506119e59050848483613514565b604080516001600160a01b038581168252602082018490528616917f3be5b7a71e84ed12875d241991c70855ac5817d847039e17a9d895c1ceb0f18a910160405180910390a2611a66565b7f8e21091fbff1b481f4a0383146b43469a9f1bfc97275d232206e61929bf9541a604051611a5d906148e2565b60405180910390a15b50505050565b6000611a7760085490565b8210611ada5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610aec565b60088281548110611aed57611aed614bd8565b90600052602060002001549050919050565b30331480611b175750600c546001600160a01b031633145b80611b3157503360009081526016602052604090205460ff165b611b4d5760405162461bcd60e51b8152600401610aec90614a16565b8051611b6090601c90602084019061425d565b507f5411e8ebf1636d9e83d5fc4900bf80cbac82e8790da2a4c94db4895e889eedf681604051610b329190614837565b30331480611ba85750600c546001600160a01b031633145b80611bc257503360009081526016602052604090205460ff165b611bde5760405162461bcd60e51b8152600401610aec90614a16565b60005b602b54811015611d40576000602b8281548110611c0057611c00614bd8565b600091825260209091200154604051631916558760e01b81526001600160a01b039091166004820181905291503090631916558790602401600060405180830381600087803b158015611c5257600080fd5b505af1925050508015611c63575060015b611d2d57611c6f614c04565b806308c379a01415611ccc5750611c84614c20565b80611c8f5750611cce565b7fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab81604051611cbe9190614837565b60405180910390a150611d2d565b505b3d808015611cf8576040519150601f19603f3d011682016040523d82523d6000602084013e611cfd565b606091505b507fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab81604051611cbe9190614837565b5080611d3881614b51565b915050611be1565b50565b30331480611d5b5750600c546001600160a01b031633145b80611d7557503360009081526016602052604090205460ff165b611d915760405162461bcd60e51b8152600401610aec90614a16565b601b8190556040518181527f62c65a566e6f2ca8aafe354c5d025fd4e75514b708e153e09a8e22d65c2c012890602001610b32565b6000818152600260205260408120546001600160a01b031680610a985760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610aec565b30331480611e555750600c546001600160a01b031633145b80611e6f57503360009081526016602052604090205460ff165b611e8b5760405162461bcd60e51b8152600401610aec90614a16565b60005b81811015610deb576000838383818110611eaa57611eaa614bd8565b9050602002016020810190611ebf91906143a9565b6001600160a01b03161415611f165760405162461bcd60e51b815260206004820152601860248201527f43616e2774206164642061207a65726f206164647265737300000000000000006044820152606401610aec565b60146000848484818110611f2c57611f2c614bd8565b9050602002016020810190611f4191906143a9565b6001600160a01b0316815260208101919091526040016000205460ff16611fb857600160146000858585818110611f7a57611f7a614bd8565b9050602002016020810190611f8f91906143a9565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790555b80611fc281614b51565b915050611e8e565b30331480611fe25750600c546001600160a01b031633145b80611ffc57503360009081526016602052604090205460ff165b6120185760405162461bcd60e51b8152600401610aec90614a16565b600081116120555760405162461bcd60e51b815260206004820152600a6024820152695a65726f20707269636560b01b6044820152606401610aec565b600082600181111561206957612069614bac565b1415612079576017819055612099565b600182600181111561208d5761208d614bac565b14156120995760188190555b7f7bba1e1c60cb9ffd449e85fd37cd4732392258eea31e30d8e4d9e24a5a82f5bf82826040516120ca92919061480b565b60405180910390a15050565b60006001600160a01b0382166121415760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610aec565b506001600160a01b031660009081526003602052604090205490565b600c546001600160a01b031633146121875760405162461bcd60e51b8152600401610aec9061492d565b61137f6000613566565b600c546001600160a01b031633146121bb5760405162461bcd60e51b8152600401610aec9061492d565b600c546001600160a01b038281169116141561220f5760405162461bcd60e51b815260206004820152601360248201527221b0b713ba103234b9b0b136329037bbb732b960691b6044820152606401610aec565b6001600160a01b03166000908152601660205260409020805460ff19169055565b601e54600090158015906122465750601e544210155b80156122615750601f54601e5461225d9190614a39565b4211155b905090565b60006011828154811061227b5761227b614bd8565b6000918252602090912001546001600160a01b031692915050565b303314806122ae5750600c546001600160a01b031633145b806122c857503360009081526016602052604090205460ff165b6122e45760405162461bcd60e51b8152600401610aec90614a16565b601d5460ff16156123075760405162461bcd60e51b8152600401610aec906149b3565b6001600160a01b03821661235d5760405162461bcd60e51b815260206004820152601f60248201527f43616e27742061697264726f7020746f2061207a65726f2061646472657373006044820152606401610aec565b612368338383611622565b604080516001600160a01b0384168152602081018390527f7bd6d4be1decdc27a9ed9c7ccdf5bb7cc38e31b3647b958c6b37162a2296c0fa91016120ca565b606060018054610b4c90614aea565b6018543360009081526016602052604081205490919060ff161515600114156123e157506000919050565b6123e9612230565b8061240857503360009081526014602052604090205460ff1615156001145b80156124245750601b5433600090815260156020526040902054105b1561242e57506017545b919050565b6001600160a01b03821633141561248c5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610aec565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6125023383613250565b61251e5760405162461bcd60e51b8152600401610aec90614962565b611a66848484846135b8565b600c546001600160a01b031633146125545760405162461bcd60e51b8152600401610aec9061492d565b6001600160a01b03166000908152601660205260409020805460ff19166001179055565b6060610a98826135eb565b3033148061259b5750600c546001600160a01b031633145b806125b557503360009081526016602052604090205460ff165b6125d15760405162461bcd60e51b8152600401610aec90614a16565b60006125dc60085490565b601d5490915060ff16156126025760405162461bcd60e51b8152600401610aec906149b3565b600082116126435760405162461bcd60e51b815260206004820152600e60248201526d416d6f756e74206973207a65726f60901b6044820152606401610aec565b601a5482111561268f5760405162461bcd60e51b8152602060048201526017602482015276105b5bdd5b9d08195e18d959591cc81b585e081b5a5b9d604a1b6044820152606401610aec565b60195461269c8383614a39565b11156126df5760405162461bcd60e51b815260206004820152601260248201527113585e081cdd5c1c1b1e481c995858da195960721b6044820152606401610aec565b60015b828111611a66576126f7846115c08385614a39565b8061270181614b51565b9150506126e2565b303314806127215750600c546001600160a01b031633145b8061273b57503360009081526016602052604090205460ff165b6127575760405162461bcd60e51b8152600401610aec90614a16565b60005b81811015610deb57600083838381811061277657612776614bd8565b905060200201602081019061278b91906143a9565b6001600160a01b031614156127e25760405162461bcd60e51b815260206004820152601b60248201527f43616e27742072656d6f76652061207a65726f206164647265737300000000006044820152606401610aec565b601460008484848181106127f8576127f8614bd8565b905060200201602081019061280d91906143a9565b6001600160a01b0316815260208101919091526040016000205460ff1615156001141561288a5760006014600085858581811061284c5761284c614bd8565b905060200201602081019061286191906143a9565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790555b8061289481614b51565b91505061275a565b600c546001600160a01b031633146128c65760405162461bcd60e51b8152600401610aec9061492d565b6001600160a01b03811661292b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610aec565b611d4081613566565b3033148061294c5750600c546001600160a01b031633145b8061296657503360009081526016602052604090205460ff165b6129825760405162461bcd60e51b8152600401610aec90614a16565b604080518082018252428082526020918201849052601e819055601f8490558251818152918201849052917f5a0b03f62508df6436b14c534559675bcce97195274e073feb68cebfd1c475d091016120ca565b60006001600160e01b0319821663152a902d60e11b1480610a985750610a988261374d565b6000908152600260205260409020546001600160a01b0316151590565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612a4c82611dc6565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b606030331480612a9f5750600c546001600160a01b031633145b80612ab957503360009081526016602052604090205460ff165b612ad55760405162461bcd60e51b8152600401610aec90614a16565b6040805160108082526102208201909252600091829190602082016102008036833701905050905060005b6009811015612b6557600060366000602d8460098110612b2257612b22614bd8565b0154600160801b90046001600160401b031681526020810191909152604001600020805460ff191691151591909117905580612b5d81614b51565b915050612b00565b5060005b6009811015612daf5784602d8260098110612b8657612b86614bd8565b01546001600160401b03161115612b9c57612daf565b84602d8260098110612bb057612bb0614bd8565b01546001600160401b031611801590612bed57506000602d8260098110612bd957612bd9614bd8565b0154600160401b90046001600160401b0316115b8015612c33575060366000602d8360098110612c0b57612c0b614bd8565b0154600160801b90046001600160401b0316815260208101919091526040016000205460ff16155b15612d9d5760005b612c8d602d8360098110612c5157612c51614bd8565b0154600160c01b90046001600160401b0316602d8460098110612c7657612c76614bd8565b0154600160401b90046001600160401b0316613772565b811015612d5157602d8260098110612ca757612ca7614bd8565b018054600160401b90046001600160401b0316906008612cc683614ac7565b91906101000a8154816001600160401b0302191690836001600160401b0316021790555050602d8260098110612cfe57612cfe614bd8565b01548351600160801b9091046001600160401b031690849086908110612d2657612d26614bd8565b602090810291909101015283612d3b81614b51565b9450508080612d4990614b51565b915050612c3b565b50600160366000602d8460098110612d6b57612d6b614bd8565b0154600160801b90046001600160401b031681526020810191909152604001600020805460ff19169115159190911790555b80612da781614b51565b915050612b69565b506000826001600160401b03811115612dca57612dca614bee565b604051908082528060200260200182016040528015612df3578160200160208202803683370190505b50905060005b83811015612e4a57828181518110612e1357612e13614bd8565b6020026020010151828281518110612e2d57612e2d614bd8565b602090810291909101015280612e4281614b51565b915050612df9565b50949350505050565b600030331480612e6d5750600c546001600160a01b031633145b80612e8757503360009081526016602052604090205460ff165b612ea35760405162461bcd60e51b8152600401610aec90614a16565b6000612eae60085490565b90508015612ed6576000612ec3828686613788565b90508015612ed4579150610a989050565b505b5060009392505050565b30331480612ef85750600c546001600160a01b031633145b80612f1257503360009081526016602052604090205460ff165b612f2e5760405162461bcd60e51b8152600401610aec90614a16565b6001600160a01b038216612f545760405162461bcd60e51b8152600401610aec906149df565b80471015612fbe5760405162461bcd60e51b815260206004820152603160248201527f4e6f2073756666696369656e742066756e6420696e20636f6e747261637420746044820152706f2070617920746865206164647265737360781b6064820152608401610aec565b600080836001600160a01b03168360405160006040518083038185875af1925050503d806000811461300c576040519150601f19603f3d011682016040523d82523d6000602084013e613011565b606091505b509150915081156130255761302583613822565b8181604051602001613037919061475e565b6040516020818303038152906040529061161b5760405162461bcd60e51b8152600401610aec9190614837565b61306d826129fa565b6130d05760405162461bcd60e51b815260206004820152602e60248201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60448201526d32bc34b9ba32b73a103a37b5b2b760911b6064820152608401610aec565b6000828152600a602090815260409091208251610deb9284019061425d565b600d546001600160a01b0384166000908152600f6020526040812054909183916131199086614a65565b6131239190614a51565b61312d9190614a84565b90505b9392505050565b804710156131875760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610aec565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146131d4576040519150601f19603f3d011682016040523d82523d6000602084013e6131d9565b606091505b5050905080610deb5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610aec565b600061325b826129fa565b6132bc5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610aec565b60006132c783611dc6565b9050806001600160a01b0316846001600160a01b031614806133025750836001600160a01b03166132f784610bcf565b6001600160a01b0316145b8061333257506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b031661334d82611dc6565b6001600160a01b0316146133b55760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610aec565b6001600160a01b0382166134175760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610aec565b61342283838361383c565b61342d600082612a17565b6001600160a01b0383166000908152600360205260408120805460019290613456908490614a84565b90915550506001600160a01b0382166000908152600360205260408120805460019290613484908490614a39565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60006131308284614a65565b6110a9828260405180602001604052806000815250613847565b611d408161387a565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610deb9084906138ba565b600c80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6135c384848461333a565b6135cf8484848461398c565b611a665760405162461bcd60e51b8152600401610aec9061484a565b60606135f6826129fa565b61365c5760405162461bcd60e51b815260206004820152603160248201527f45524337323155524953746f726167653a2055524920717565727920666f72206044820152703737b732bc34b9ba32b73a103a37b5b2b760791b6064820152608401610aec565b6000828152600a60205260408120805461367590614aea565b80601f01602080910402602001604051908101604052809291908181526020018280546136a190614aea565b80156136ee5780601f106136c3576101008083540402835291602001916136ee565b820191906000526020600020905b8154815290600101906020018083116136d157829003601f168201915b5050505050905060006136ff613a99565b9050805160001415613712575092915050565b81511561374457808260405160200161372c92919061472f565b60405160208183030381529060405292505050919050565b61333284613aa8565b60006001600160e01b0319821663780e9d6360e01b1480610a985750610a9882613b72565b60008183106137815781613130565b5090919050565b600080613796600143614a84565b90506137a461010085614b6c565b4311156137c4576137b761010085614b6c565b6137c19043614a84565b90505b60008542861842600036883388406040516020016137e8979695949392919061479b565b6040516020818303038152906040528051906020012060001c61380b9190614b6c565b9050613818816001614a39565b9695505050505050565b80600e60008282546138349190614a39565b909155505050565b610deb838383613bc2565b6138518383613c7a565b61385e600084848461398c565b610deb5760405162461bcd60e51b8152600401610aec9061484a565b61388381613db9565b6000818152600a60205260409020805461389c90614aea565b159050611d40576000818152600a60205260408120611d40916142e1565b600061390f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e609092919063ffffffff16565b805190915015610deb578080602001905181019061392d91906145aa565b610deb5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610aec565b60006001600160a01b0384163b15613a8e57604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906139d09033908990889088906004016147d8565b602060405180830381600087803b1580156139ea57600080fd5b505af1925050508015613a1a575060408051601f3d908101601f19168201909252613a17918101906145e4565b60015b613a74573d808015613a48576040519150601f19603f3d011682016040523d82523d6000602084013e613a4d565b606091505b508051613a6c5760405162461bcd60e51b8152600401610aec9061484a565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050613332565b506001949350505050565b6060601c8054610b4c90614aea565b6060613ab3826129fa565b613b175760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610aec565b6000613b21613a99565b90506000815111613b415760405180602001604052806000815250613130565b80613b4b84613e6f565b604051602001613b5c92919061472f565b6040516020818303038152906040529392505050565b60006001600160e01b031982166380ac58cd60e01b1480613ba357506001600160e01b03198216635b5e139f60e01b145b80610a9857506301ffc9a760e01b6001600160e01b0319831614610a98565b6001600160a01b038316613c1d57613c1881600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b613c40565b816001600160a01b0316836001600160a01b031614613c4057613c408382613f6c565b6001600160a01b038216613c5757610deb81614009565b826001600160a01b0316826001600160a01b031614610deb57610deb82826140b8565b6001600160a01b038216613cd05760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610aec565b613cd9816129fa565b15613d265760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610aec565b613d326000838361383c565b6001600160a01b0382166000908152600360205260408120805460019290613d5b908490614a39565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000613dc482611dc6565b9050613dd28160008461383c565b613ddd600083612a17565b6001600160a01b0381166000908152600360205260408120805460019290613e06908490614a84565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b606061312d84846000856140fc565b606081613e935750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613ebd5780613ea781614b51565b9150613eb69050600a83614a51565b9150613e97565b6000816001600160401b03811115613ed757613ed7614bee565b6040519080825280601f01601f191660200182016040528015613f01576020820181803683370190505b5090505b841561333257613f16600183614a84565b9150613f23600a86614b6c565b613f2e906030614a39565b60f81b818381518110613f4357613f43614bd8565b60200101906001600160f81b031916908160001a905350613f65600a86614a51565b9450613f05565b60006001613f79846120d6565b613f839190614a84565b600083815260076020526040902054909150808214613fd6576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b60085460009061401b90600190614a84565b6000838152600960205260408120546008805493945090928490811061404357614043614bd8565b90600052602060002001549050806008838154811061406457614064614bd8565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061409c5761409c614bc2565b6001900381819060005260206000200160009055905550505050565b60006140c3836120d6565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b60608247101561415d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610aec565b843b6141ab5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610aec565b600080866001600160a01b031685876040516141c79190614713565b60006040518083038185875af1925050503d8060008114614204576040519150601f19603f3d011682016040523d82523d6000602084013e614209565b606091505b5091509150614219828286614224565b979650505050505050565b60608315614233575081613130565b8251156142435782518084602001fd5b8160405162461bcd60e51b8152600401610aec9190614837565b82805461426990614aea565b90600052602060002090601f01602090048101928261428b57600085556142d1565b82601f106142a457805160ff19168380011785556142d1565b828001600101855582156142d1579182015b828111156142d15782518255916020019190600101906142b6565b506142dd929150614317565b5090565b5080546142ed90614aea565b6000825580601f106142fd575050565b601f016020900490600052602060002090810190611d4091905b5b808211156142dd5760008155600101614318565b60006001600160401b0383111561434557614345614bee565b60405161435c601f8501601f191660200182614b25565b80915083815284848401111561437157600080fd5b83836020830137600060208583010152509392505050565b600082601f83011261439a57600080fd5b6131308383356020850161432c565b6000602082840312156143bb57600080fd5b813561313081614ca9565b600080604083850312156143d957600080fd5b82356143e481614ca9565b915060208301356143f481614ca9565b809150509250929050565b60008060006060848603121561441457600080fd5b833561441f81614ca9565b9250602084013561442f81614ca9565b929592945050506040919091013590565b6000806000806080858703121561445657600080fd5b843561446181614ca9565b9350602085013561447181614ca9565b92506040850135915060608501356001600160401b0381111561449357600080fd5b8501601f810187136144a457600080fd5b6144b38782356020840161432c565b91505092959194509250565b600080604083850312156144d257600080fd5b82356144dd81614ca9565b915060208301356143f481614cbe565b6000806040838503121561450057600080fd5b823561450b81614ca9565b946020939093013593505050565b6000806020838503121561452c57600080fd5b82356001600160401b038082111561454357600080fd5b818501915085601f83011261455757600080fd5b81358181111561456657600080fd5b8660208260051b850101111561457b57600080fd5b60209290920196919550909350505050565b60006020828403121561459f57600080fd5b813561313081614cbe565b6000602082840312156145bc57600080fd5b815161313081614cbe565b6000602082840312156145d957600080fd5b813561313081614ccc565b6000602082840312156145f657600080fd5b815161313081614ccc565b6000806040838503121561461457600080fd5b82356002811061450b57600080fd5b60006020828403121561463557600080fd5b81356001600160401b0381111561464b57600080fd5b61333284828501614389565b60006020828403121561466957600080fd5b5035919050565b60006020828403121561468257600080fd5b5051919050565b6000806040838503121561469c57600080fd5b8235915060208301356001600160401b038111156146b957600080fd5b61126e85828601614389565b600080604083850312156146d857600080fd5b50508035926020909101359150565b600081518084526146ff816020860160208601614a9b565b601f01601f19169290920160200192915050565b60008251614725818460208701614a9b565b9190910192915050565b60008351614741818460208801614a9b565b835190830190614755818360208801614a9b565b01949350505050565b742330b4b632b2103a379039b2b7321022ba3432b91d60591b81526000825161478e816015850160208701614a9b565b9190910160150192915050565b878152866020820152848660408301376040940193840192909252606090811b6001600160601b0319169083015260748201526094019392505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613818908301846146e7565b604081016002841061482d57634e487b7160e01b600052602160045260246000fd5b9281526020015290565b60208152600061313060208301846146e7565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526026908201527f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060408201526573686172657360d01b606082015260800190565b6020808252602b908201527f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060408201526a191d59481c185e5b595b9d60aa1b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526012908201527110dbdb9d1c9858dd081a5cc81c185d5cd95960721b604082015260600190565b60208082526018908201527f43616e2774207061792061207a65726f20616464726573730000000000000000604082015260600190565b6020808252600990820152682737ba1030b236b4b760b91b604082015260600190565b60008219821115614a4c57614a4c614b80565b500190565b600082614a6057614a60614b96565b500490565b6000816000190483118215151615614a7f57614a7f614b80565b500290565b600082821015614a9657614a96614b80565b500390565b60005b83811015614ab6578181015183820152602001614a9e565b83811115611a665750506000910152565b60006001600160401b03821680614ae057614ae0614b80565b6000190192915050565b600181811c90821680614afe57607f821691505b60208210811415614b1f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f191681016001600160401b0381118282101715614b4a57614b4a614bee565b6040525050565b6000600019821415614b6557614b65614b80565b5060010190565b600082614b7b57614b7b614b96565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d1115614c1d5760046000803e5060005160e01c5b90565b600060443d1015614c2e5790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715614c5d57505050505090565b8285019150815181811115614c755750505050505090565b843d8701016020828501011115614c8f5750505050505090565b614c9e60208286010187614b25565b509095945050505050565b6001600160a01b0381168114611d4057600080fd5b8015158114611d4057600080fd5b6001600160e01b031981168114611d4057600080fdfea2646970667358221220414d9951eb094e9f3eecc45ff7dcf1c7de317858d1ad8616b1355e70b4b69e2c64736f6c63430008070033

Deployed Bytecode

0x60806040526004361061031e5760003560e01c80636352211e116101ab578063a22cb465116100f7578063d79779b211610095578063e985e9c51161006f578063e985e9c5146109e4578063eff42f2e14610a2d578063f2fde38b14610a4d578063f5d94f6a14610a6d57600080fd5b8063d79779b214610969578063d936547e1461099f578063e33b7de3146109cf57600080fd5b8063bea532ff116100d1578063bea532ff146108d3578063c87b56dd146108f3578063cbce4c9714610913578063ce7c2ac21461093357600080fd5b8063a22cb46514610866578063b134a06714610886578063b88d4fde146108b357600080fd5b806389b1f38e116101645780638da5cb5b1161013e5780638da5cb5b146107e857806395d89b41146108065780639852595c1461081b57806398d5fdca1461085157600080fd5b806389b1f38e146107935780638b83209b146107a85780638ba4cc3c146107c857600080fd5b80636352211e146106de5780636496d3fc146106fe5780636a00670b1461071e57806370a082311461073e578063715018a61461075e578063751e9a9c1461077357600080fd5b80633a98ef391161026a578063429b62e5116102235780634f6ccce7116101fd5780634f6ccce71461066957806355f804b3146106895780635be7fde8146106a95780635f19d2fc146106be57600080fd5b8063429b62e514610606578063431d729f1461063657806348b750441461064957600080fd5b80633a98ef39146105435780633ccfd60b14610558578063406072a91461056d57806340c10f19146105b357806342842e0e146105c657806342966c68146105e657600080fd5b80630eecae21116102d757806319165587116102b157806319165587146104a457806323b872dd146104c45780632a55205a146104e45780632f745c591461052357600080fd5b80630eecae211461045d578063162094c41461046557806318160ddd1461048557600080fd5b806301ffc9a71461036c57806302329a29146103a157806306fdde03146103c3578063081812fc146103e5578063088a4ed01461041d578063095ea7b31461043d57600080fd5b36610367577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be77033604080516001600160a01b0390921682523460208301520160405180910390a1005b600080fd5b34801561037857600080fd5b5061038c6103873660046145c7565b610a8d565b60405190151581526020015b60405180910390f35b3480156103ad57600080fd5b506103c16103bc36600461458d565b610a9e565b005b3480156103cf57600080fd5b506103d8610b3d565b6040516103989190614837565b3480156103f157600080fd5b50610405610400366004614657565b610bcf565b6040516001600160a01b039091168152602001610398565b34801561042957600080fd5b506103c1610438366004614657565b610c57565b34801561044957600080fd5b506103c16104583660046144ed565b610cda565b6103c1610df0565b34801561047157600080fd5b506103c1610480366004614689565b610ffc565b34801561049157600080fd5b506008545b604051908152602001610398565b3480156104b057600080fd5b506103c16104bf3660046143a9565b6110ad565b3480156104d057600080fd5b506103c16104df3660046143ff565b6111f2565b3480156104f057600080fd5b506105046104ff3660046146c5565b611223565b604080516001600160a01b039093168352602083019190915201610398565b34801561052f57600080fd5b5061049661053e3660046144ed565b611278565b34801561054f57600080fd5b50600d54610496565b34801561056457600080fd5b506103c161130e565b34801561057957600080fd5b506104966105883660046143c6565b6001600160a01b03918216600090815260136020908152604080832093909416825291909152205490565b6103c16105c13660046144ed565b611381565b3480156105d257600080fd5b506103c16105e13660046143ff565b611622565b3480156105f257600080fd5b506103c1610601366004614657565b61163d565b34801561061257600080fd5b5061038c6106213660046143a9565b60166020526000908152604090205460ff1681565b6103c1610644366004614657565b6116a9565b34801561065557600080fd5b506103c16106643660046143c6565b611860565b34801561067557600080fd5b50610496610684366004614657565b611a6c565b34801561069557600080fd5b506103c16106a4366004614623565b611aff565b3480156106b557600080fd5b506103c1611b90565b3480156106ca57600080fd5b506103c16106d9366004614657565b611d43565b3480156106ea57600080fd5b506104056106f9366004614657565b611dc6565b34801561070a57600080fd5b506103c1610719366004614519565b611e3d565b34801561072a57600080fd5b506103c1610739366004614601565b611fca565b34801561074a57600080fd5b506104966107593660046143a9565b6120d6565b34801561076a57600080fd5b506103c161215d565b34801561077f57600080fd5b506103c161078e3660046143a9565b612191565b34801561079f57600080fd5b5061038c612230565b3480156107b457600080fd5b506104056107c3366004614657565b612266565b3480156107d457600080fd5b506103c16107e33660046144ed565b612296565b3480156107f457600080fd5b50600c546001600160a01b0316610405565b34801561081257600080fd5b506103d86123a7565b34801561082757600080fd5b506104966108363660046143a9565b6001600160a01b031660009081526010602052604090205490565b34801561085d57600080fd5b506104966123b6565b34801561087257600080fd5b506103c16108813660046144bf565b612433565b34801561089257600080fd5b506104966108a13660046143a9565b60156020526000908152604090205481565b3480156108bf57600080fd5b506103c16108ce366004614440565b6124f8565b3480156108df57600080fd5b506103c16108ee3660046143a9565b61252a565b3480156108ff57600080fd5b506103d861090e366004614657565b612578565b34801561091f57600080fd5b506103c161092e3660046144ed565b612583565b34801561093f57600080fd5b5061049661094e3660046143a9565b6001600160a01b03166000908152600f602052604090205490565b34801561097557600080fd5b506104966109843660046143a9565b6001600160a01b031660009081526012602052604090205490565b3480156109ab57600080fd5b5061038c6109ba3660046143a9565b60146020526000908152604090205460ff1681565b3480156109db57600080fd5b50600e54610496565b3480156109f057600080fd5b5061038c6109ff3660046143c6565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b348015610a3957600080fd5b506103c1610a48366004614519565b612709565b348015610a5957600080fd5b506103c1610a683660046143a9565b61289c565b348015610a7957600080fd5b506103c1610a88366004614657565b612934565b6000610a98826129d5565b92915050565b30331480610ab65750600c546001600160a01b031633145b80610ad057503360009081526016602052604090205460ff165b610af55760405162461bcd60e51b8152600401610aec90614a16565b60405180910390fd5b601d805460ff19168215159081179091556040519081527f0e2fb031ee032dc02d8011dc50b816eb450cf856abd8261680dac74f72165bd2906020015b60405180910390a150565b606060008054610b4c90614aea565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7890614aea565b8015610bc55780601f10610b9a57610100808354040283529160200191610bc5565b820191906000526020600020905b815481529060010190602001808311610ba857829003601f168201915b5050505050905090565b6000610bda826129fa565b610c3b5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610aec565b506000908152600460205260409020546001600160a01b031690565b30331480610c6f5750600c546001600160a01b031633145b80610c8957503360009081526016602052604090205460ff165b610ca55760405162461bcd60e51b8152600401610aec90614a16565b601a8190556040518181527f71ef44637f994911a9fa6bc89bc19c9bbf6f510a992e74f90880ffbccd7b2c6b90602001610b32565b6000610ce582611dc6565b9050806001600160a01b0316836001600160a01b03161415610d535760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610aec565b336001600160a01b0382161480610d6f5750610d6f81336109ff565b610de15760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610aec565b610deb8383612a17565b505050565b30331480610e085750600c546001600160a01b031633145b80610e2257503360009081526016602052604090205460ff165b610e3e5760405162461bcd60e51b8152600401610aec90614a16565b601d5460ff1615610e615760405162461bcd60e51b8152600401610aec906149b3565b610e69611b90565b6000610e7c610e7760085490565b612a85565b90504460005b8251811015610deb576000610e978284612e53565b905080610eda5760405162461bcd60e51b8152602060048201526011602482015270125b98dbdc9c9958dd081d1bdad95b9259607a1b6044820152606401610aec565b6000610ee582611dc6565b90506001600160a01b038116610f0d5760405162461bcd60e51b8152600401610aec906149df565b610f428166038d7ea4c68000878681518110610f2b57610f2b614bd8565b6020026020010151610f3d9190614a65565b612ee0565b6040516001600160601b0319606083901b1660208201526034016040516020818303038152906040528051906020012060001c841893507f1c2ae1f7e99dbbbfe25aac964f3889ea68259d88b74709f53037a6fb930bb02a8282878681518110610fae57610fae614bd8565b6020026020010151604051610fdf939291909283526001600160a01b03919091166020830152604082015260600190565b60405180910390a150508080610ff490614b51565b915050610e82565b303314806110145750600c546001600160a01b031633145b8061102e57503360009081526016602052604090205460ff165b61104a5760405162461bcd60e51b8152600401610aec90614a16565b611053826129fa565b61109f5760405162461bcd60e51b815260206004820152601c60248201527f55524920736574206f66206e6f6e6578697374656e7420746f6b656e000000006044820152606401610aec565b6110a98282613064565b5050565b6001600160a01b0381166000908152600f60205260409020546110e25760405162461bcd60e51b8152600401610aec9061489c565b60006110ed600e5490565b6110f79047614a39565b90506000611124838361111f866001600160a01b031660009081526010602052604090205490565b6130ef565b905080156111c5576001600160a01b03831660009081526010602052604081208054839290611154908490614a39565b9250508190555080600e600082825461116d9190614a39565b9091555061117d90508382613137565b604080516001600160a01b0385168152602081018390527fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b05691015b60405180910390a1505050565b7f8e21091fbff1b481f4a0383146b43469a9f1bfc97275d232206e61929bf9541a6040516111b8906148e2565b6111fc3382613250565b6112185760405162461bcd60e51b8152600401610aec90614962565b610deb83838361333a565b60408051808201909152600b546001600160a01b038116808352600160a01b90910462ffffff16602083018190529091600091612710906112649086614a65565b61126e9190614a51565b9150509250929050565b6000611283836120d6565b82106112e55760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610aec565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b303314806113265750600c546001600160a01b031633145b8061134057503360009081526016602052604090205460ff165b61135c5760405162461bcd60e51b8152600401610aec90614a16565b611364611b90565b61137f611379600c546001600160a01b031690565b47612ee0565b565b600061138c60085490565b9050600060175461139b6123b6565b601d549114915060ff16156113c25760405162461bcd60e51b8152600401610aec906149b3565b600083116114035760405162461bcd60e51b815260206004820152600e60248201526d416d6f756e74206973207a65726f60901b6044820152606401610aec565b601a5483111561144f5760405162461bcd60e51b8152602060048201526017602482015276105b5bdd5b9d08195e18d959591cc81b585e081b5a5b9d604a1b6044820152606401610aec565b60195461145c8484614a39565b111561149f5760405162461bcd60e51b815260206004820152601260248201527113585e081cdd5c1c1b1e481c995858da195960721b6044820152606401610aec565b3360009081526016602052604090205460ff1615156001146115a857801561154857601b546001600160a01b0385166000908152601560205260409020546114e8908590614a39565b11156115485760405162461bcd60e51b815260206004820152602960248201527f4d617820646973636f756e746564204e465420657863656564656420666f72206044820152683a3434b9903ab9b2b960b91b6064820152608401610aec565b3461155b846115556123b6565b906134e5565b146115a85760405162461bcd60e51b815260206004820152601f60248201527f45746865722076616c75652073656e74206973206e6f7420636f7272656374006044820152606401610aec565b60015b83811161161b576115c5856115c08386614a39565b6134f1565b8115611609576001600160a01b0385166000908152601560205260409020546115ef906001614a39565b6001600160a01b0386166000908152601560205260409020555b8061161381614b51565b9150506115ab565b5050505050565b610deb838383604051806020016040528060008152506124f8565b303314806116555750600c546001600160a01b031633145b8061166f57503360009081526016602052604090205460ff165b61168b5760405162461bcd60e51b8152600401610aec90614a16565b6116948161350b565b60016019546116a39190614a84565b60195550565b303314806116c15750600c546001600160a01b031633145b806116db57503360009081526016602052604090205460ff165b6116f75760405162461bcd60e51b8152600401610aec90614a16565b601d5460ff161561171a5760405162461bcd60e51b8152600401610aec906149b3565b611722611b90565b604080516001600160601b031941606090811b8216602080850191909152845180850360140181526034850186528051908201203390921b9092166054840152835180840360480181526068909301909352815191012060006117858383612e53565b9050806117c85760405162461bcd60e51b8152602060048201526011602482015270125b98dbdc9c9958dd081d1bdad95b9259607a1b6044820152606401610aec565b60006117d382611dc6565b90506001600160a01b0381166117fb5760405162461bcd60e51b8152600401610aec906149df565b61181081610f3d66038d7ea4c6800088614a65565b604080518381526001600160a01b03831660208201529081018690527f1c2ae1f7e99dbbbfe25aac964f3889ea68259d88b74709f53037a6fb930bb02a9060600160405180910390a15050505050565b6001600160a01b0381166000908152600f60205260409020546118955760405162461bcd60e51b8152600401610aec9061489c565b6001600160a01b0382166000908152601260205260408120546040516370a0823160e01b81523060048201526001600160a01b038516906370a082319060240160206040518083038186803b1580156118ed57600080fd5b505afa158015611901573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119259190614670565b61192f9190614a39565b90506000611968838361111f87876001600160a01b03918216600090815260136020908152604080832093909416825291909152205490565b90508015611a30576001600160a01b038085166000908152601360209081526040808320938716835292905290812080548392906119a7908490614a39565b90915550506001600160a01b038416600090815260126020526040812080548392906119d4908490614a39565b909155506119e59050848483613514565b604080516001600160a01b038581168252602082018490528616917f3be5b7a71e84ed12875d241991c70855ac5817d847039e17a9d895c1ceb0f18a910160405180910390a2611a66565b7f8e21091fbff1b481f4a0383146b43469a9f1bfc97275d232206e61929bf9541a604051611a5d906148e2565b60405180910390a15b50505050565b6000611a7760085490565b8210611ada5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610aec565b60088281548110611aed57611aed614bd8565b90600052602060002001549050919050565b30331480611b175750600c546001600160a01b031633145b80611b3157503360009081526016602052604090205460ff165b611b4d5760405162461bcd60e51b8152600401610aec90614a16565b8051611b6090601c90602084019061425d565b507f5411e8ebf1636d9e83d5fc4900bf80cbac82e8790da2a4c94db4895e889eedf681604051610b329190614837565b30331480611ba85750600c546001600160a01b031633145b80611bc257503360009081526016602052604090205460ff165b611bde5760405162461bcd60e51b8152600401610aec90614a16565b60005b602b54811015611d40576000602b8281548110611c0057611c00614bd8565b600091825260209091200154604051631916558760e01b81526001600160a01b039091166004820181905291503090631916558790602401600060405180830381600087803b158015611c5257600080fd5b505af1925050508015611c63575060015b611d2d57611c6f614c04565b806308c379a01415611ccc5750611c84614c20565b80611c8f5750611cce565b7fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab81604051611cbe9190614837565b60405180910390a150611d2d565b505b3d808015611cf8576040519150601f19603f3d011682016040523d82523d6000602084013e611cfd565b606091505b507fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab81604051611cbe9190614837565b5080611d3881614b51565b915050611be1565b50565b30331480611d5b5750600c546001600160a01b031633145b80611d7557503360009081526016602052604090205460ff165b611d915760405162461bcd60e51b8152600401610aec90614a16565b601b8190556040518181527f62c65a566e6f2ca8aafe354c5d025fd4e75514b708e153e09a8e22d65c2c012890602001610b32565b6000818152600260205260408120546001600160a01b031680610a985760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610aec565b30331480611e555750600c546001600160a01b031633145b80611e6f57503360009081526016602052604090205460ff165b611e8b5760405162461bcd60e51b8152600401610aec90614a16565b60005b81811015610deb576000838383818110611eaa57611eaa614bd8565b9050602002016020810190611ebf91906143a9565b6001600160a01b03161415611f165760405162461bcd60e51b815260206004820152601860248201527f43616e2774206164642061207a65726f206164647265737300000000000000006044820152606401610aec565b60146000848484818110611f2c57611f2c614bd8565b9050602002016020810190611f4191906143a9565b6001600160a01b0316815260208101919091526040016000205460ff16611fb857600160146000858585818110611f7a57611f7a614bd8565b9050602002016020810190611f8f91906143a9565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790555b80611fc281614b51565b915050611e8e565b30331480611fe25750600c546001600160a01b031633145b80611ffc57503360009081526016602052604090205460ff165b6120185760405162461bcd60e51b8152600401610aec90614a16565b600081116120555760405162461bcd60e51b815260206004820152600a6024820152695a65726f20707269636560b01b6044820152606401610aec565b600082600181111561206957612069614bac565b1415612079576017819055612099565b600182600181111561208d5761208d614bac565b14156120995760188190555b7f7bba1e1c60cb9ffd449e85fd37cd4732392258eea31e30d8e4d9e24a5a82f5bf82826040516120ca92919061480b565b60405180910390a15050565b60006001600160a01b0382166121415760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610aec565b506001600160a01b031660009081526003602052604090205490565b600c546001600160a01b031633146121875760405162461bcd60e51b8152600401610aec9061492d565b61137f6000613566565b600c546001600160a01b031633146121bb5760405162461bcd60e51b8152600401610aec9061492d565b600c546001600160a01b038281169116141561220f5760405162461bcd60e51b815260206004820152601360248201527221b0b713ba103234b9b0b136329037bbb732b960691b6044820152606401610aec565b6001600160a01b03166000908152601660205260409020805460ff19169055565b601e54600090158015906122465750601e544210155b80156122615750601f54601e5461225d9190614a39565b4211155b905090565b60006011828154811061227b5761227b614bd8565b6000918252602090912001546001600160a01b031692915050565b303314806122ae5750600c546001600160a01b031633145b806122c857503360009081526016602052604090205460ff165b6122e45760405162461bcd60e51b8152600401610aec90614a16565b601d5460ff16156123075760405162461bcd60e51b8152600401610aec906149b3565b6001600160a01b03821661235d5760405162461bcd60e51b815260206004820152601f60248201527f43616e27742061697264726f7020746f2061207a65726f2061646472657373006044820152606401610aec565b612368338383611622565b604080516001600160a01b0384168152602081018390527f7bd6d4be1decdc27a9ed9c7ccdf5bb7cc38e31b3647b958c6b37162a2296c0fa91016120ca565b606060018054610b4c90614aea565b6018543360009081526016602052604081205490919060ff161515600114156123e157506000919050565b6123e9612230565b8061240857503360009081526014602052604090205460ff1615156001145b80156124245750601b5433600090815260156020526040902054105b1561242e57506017545b919050565b6001600160a01b03821633141561248c5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610aec565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6125023383613250565b61251e5760405162461bcd60e51b8152600401610aec90614962565b611a66848484846135b8565b600c546001600160a01b031633146125545760405162461bcd60e51b8152600401610aec9061492d565b6001600160a01b03166000908152601660205260409020805460ff19166001179055565b6060610a98826135eb565b3033148061259b5750600c546001600160a01b031633145b806125b557503360009081526016602052604090205460ff165b6125d15760405162461bcd60e51b8152600401610aec90614a16565b60006125dc60085490565b601d5490915060ff16156126025760405162461bcd60e51b8152600401610aec906149b3565b600082116126435760405162461bcd60e51b815260206004820152600e60248201526d416d6f756e74206973207a65726f60901b6044820152606401610aec565b601a5482111561268f5760405162461bcd60e51b8152602060048201526017602482015276105b5bdd5b9d08195e18d959591cc81b585e081b5a5b9d604a1b6044820152606401610aec565b60195461269c8383614a39565b11156126df5760405162461bcd60e51b815260206004820152601260248201527113585e081cdd5c1c1b1e481c995858da195960721b6044820152606401610aec565b60015b828111611a66576126f7846115c08385614a39565b8061270181614b51565b9150506126e2565b303314806127215750600c546001600160a01b031633145b8061273b57503360009081526016602052604090205460ff165b6127575760405162461bcd60e51b8152600401610aec90614a16565b60005b81811015610deb57600083838381811061277657612776614bd8565b905060200201602081019061278b91906143a9565b6001600160a01b031614156127e25760405162461bcd60e51b815260206004820152601b60248201527f43616e27742072656d6f76652061207a65726f206164647265737300000000006044820152606401610aec565b601460008484848181106127f8576127f8614bd8565b905060200201602081019061280d91906143a9565b6001600160a01b0316815260208101919091526040016000205460ff1615156001141561288a5760006014600085858581811061284c5761284c614bd8565b905060200201602081019061286191906143a9565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790555b8061289481614b51565b91505061275a565b600c546001600160a01b031633146128c65760405162461bcd60e51b8152600401610aec9061492d565b6001600160a01b03811661292b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610aec565b611d4081613566565b3033148061294c5750600c546001600160a01b031633145b8061296657503360009081526016602052604090205460ff165b6129825760405162461bcd60e51b8152600401610aec90614a16565b604080518082018252428082526020918201849052601e819055601f8490558251818152918201849052917f5a0b03f62508df6436b14c534559675bcce97195274e073feb68cebfd1c475d091016120ca565b60006001600160e01b0319821663152a902d60e11b1480610a985750610a988261374d565b6000908152600260205260409020546001600160a01b0316151590565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612a4c82611dc6565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b606030331480612a9f5750600c546001600160a01b031633145b80612ab957503360009081526016602052604090205460ff165b612ad55760405162461bcd60e51b8152600401610aec90614a16565b6040805160108082526102208201909252600091829190602082016102008036833701905050905060005b6009811015612b6557600060366000602d8460098110612b2257612b22614bd8565b0154600160801b90046001600160401b031681526020810191909152604001600020805460ff191691151591909117905580612b5d81614b51565b915050612b00565b5060005b6009811015612daf5784602d8260098110612b8657612b86614bd8565b01546001600160401b03161115612b9c57612daf565b84602d8260098110612bb057612bb0614bd8565b01546001600160401b031611801590612bed57506000602d8260098110612bd957612bd9614bd8565b0154600160401b90046001600160401b0316115b8015612c33575060366000602d8360098110612c0b57612c0b614bd8565b0154600160801b90046001600160401b0316815260208101919091526040016000205460ff16155b15612d9d5760005b612c8d602d8360098110612c5157612c51614bd8565b0154600160c01b90046001600160401b0316602d8460098110612c7657612c76614bd8565b0154600160401b90046001600160401b0316613772565b811015612d5157602d8260098110612ca757612ca7614bd8565b018054600160401b90046001600160401b0316906008612cc683614ac7565b91906101000a8154816001600160401b0302191690836001600160401b0316021790555050602d8260098110612cfe57612cfe614bd8565b01548351600160801b9091046001600160401b031690849086908110612d2657612d26614bd8565b602090810291909101015283612d3b81614b51565b9450508080612d4990614b51565b915050612c3b565b50600160366000602d8460098110612d6b57612d6b614bd8565b0154600160801b90046001600160401b031681526020810191909152604001600020805460ff19169115159190911790555b80612da781614b51565b915050612b69565b506000826001600160401b03811115612dca57612dca614bee565b604051908082528060200260200182016040528015612df3578160200160208202803683370190505b50905060005b83811015612e4a57828181518110612e1357612e13614bd8565b6020026020010151828281518110612e2d57612e2d614bd8565b602090810291909101015280612e4281614b51565b915050612df9565b50949350505050565b600030331480612e6d5750600c546001600160a01b031633145b80612e8757503360009081526016602052604090205460ff165b612ea35760405162461bcd60e51b8152600401610aec90614a16565b6000612eae60085490565b90508015612ed6576000612ec3828686613788565b90508015612ed4579150610a989050565b505b5060009392505050565b30331480612ef85750600c546001600160a01b031633145b80612f1257503360009081526016602052604090205460ff165b612f2e5760405162461bcd60e51b8152600401610aec90614a16565b6001600160a01b038216612f545760405162461bcd60e51b8152600401610aec906149df565b80471015612fbe5760405162461bcd60e51b815260206004820152603160248201527f4e6f2073756666696369656e742066756e6420696e20636f6e747261637420746044820152706f2070617920746865206164647265737360781b6064820152608401610aec565b600080836001600160a01b03168360405160006040518083038185875af1925050503d806000811461300c576040519150601f19603f3d011682016040523d82523d6000602084013e613011565b606091505b509150915081156130255761302583613822565b8181604051602001613037919061475e565b6040516020818303038152906040529061161b5760405162461bcd60e51b8152600401610aec9190614837565b61306d826129fa565b6130d05760405162461bcd60e51b815260206004820152602e60248201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60448201526d32bc34b9ba32b73a103a37b5b2b760911b6064820152608401610aec565b6000828152600a602090815260409091208251610deb9284019061425d565b600d546001600160a01b0384166000908152600f6020526040812054909183916131199086614a65565b6131239190614a51565b61312d9190614a84565b90505b9392505050565b804710156131875760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610aec565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146131d4576040519150601f19603f3d011682016040523d82523d6000602084013e6131d9565b606091505b5050905080610deb5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610aec565b600061325b826129fa565b6132bc5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610aec565b60006132c783611dc6565b9050806001600160a01b0316846001600160a01b031614806133025750836001600160a01b03166132f784610bcf565b6001600160a01b0316145b8061333257506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b031661334d82611dc6565b6001600160a01b0316146133b55760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610aec565b6001600160a01b0382166134175760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610aec565b61342283838361383c565b61342d600082612a17565b6001600160a01b0383166000908152600360205260408120805460019290613456908490614a84565b90915550506001600160a01b0382166000908152600360205260408120805460019290613484908490614a39565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60006131308284614a65565b6110a9828260405180602001604052806000815250613847565b611d408161387a565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610deb9084906138ba565b600c80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6135c384848461333a565b6135cf8484848461398c565b611a665760405162461bcd60e51b8152600401610aec9061484a565b60606135f6826129fa565b61365c5760405162461bcd60e51b815260206004820152603160248201527f45524337323155524953746f726167653a2055524920717565727920666f72206044820152703737b732bc34b9ba32b73a103a37b5b2b760791b6064820152608401610aec565b6000828152600a60205260408120805461367590614aea565b80601f01602080910402602001604051908101604052809291908181526020018280546136a190614aea565b80156136ee5780601f106136c3576101008083540402835291602001916136ee565b820191906000526020600020905b8154815290600101906020018083116136d157829003601f168201915b5050505050905060006136ff613a99565b9050805160001415613712575092915050565b81511561374457808260405160200161372c92919061472f565b60405160208183030381529060405292505050919050565b61333284613aa8565b60006001600160e01b0319821663780e9d6360e01b1480610a985750610a9882613b72565b60008183106137815781613130565b5090919050565b600080613796600143614a84565b90506137a461010085614b6c565b4311156137c4576137b761010085614b6c565b6137c19043614a84565b90505b60008542861842600036883388406040516020016137e8979695949392919061479b565b6040516020818303038152906040528051906020012060001c61380b9190614b6c565b9050613818816001614a39565b9695505050505050565b80600e60008282546138349190614a39565b909155505050565b610deb838383613bc2565b6138518383613c7a565b61385e600084848461398c565b610deb5760405162461bcd60e51b8152600401610aec9061484a565b61388381613db9565b6000818152600a60205260409020805461389c90614aea565b159050611d40576000818152600a60205260408120611d40916142e1565b600061390f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e609092919063ffffffff16565b805190915015610deb578080602001905181019061392d91906145aa565b610deb5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610aec565b60006001600160a01b0384163b15613a8e57604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906139d09033908990889088906004016147d8565b602060405180830381600087803b1580156139ea57600080fd5b505af1925050508015613a1a575060408051601f3d908101601f19168201909252613a17918101906145e4565b60015b613a74573d808015613a48576040519150601f19603f3d011682016040523d82523d6000602084013e613a4d565b606091505b508051613a6c5760405162461bcd60e51b8152600401610aec9061484a565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050613332565b506001949350505050565b6060601c8054610b4c90614aea565b6060613ab3826129fa565b613b175760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610aec565b6000613b21613a99565b90506000815111613b415760405180602001604052806000815250613130565b80613b4b84613e6f565b604051602001613b5c92919061472f565b6040516020818303038152906040529392505050565b60006001600160e01b031982166380ac58cd60e01b1480613ba357506001600160e01b03198216635b5e139f60e01b145b80610a9857506301ffc9a760e01b6001600160e01b0319831614610a98565b6001600160a01b038316613c1d57613c1881600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b613c40565b816001600160a01b0316836001600160a01b031614613c4057613c408382613f6c565b6001600160a01b038216613c5757610deb81614009565b826001600160a01b0316826001600160a01b031614610deb57610deb82826140b8565b6001600160a01b038216613cd05760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610aec565b613cd9816129fa565b15613d265760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610aec565b613d326000838361383c565b6001600160a01b0382166000908152600360205260408120805460019290613d5b908490614a39565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000613dc482611dc6565b9050613dd28160008461383c565b613ddd600083612a17565b6001600160a01b0381166000908152600360205260408120805460019290613e06908490614a84565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b606061312d84846000856140fc565b606081613e935750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613ebd5780613ea781614b51565b9150613eb69050600a83614a51565b9150613e97565b6000816001600160401b03811115613ed757613ed7614bee565b6040519080825280601f01601f191660200182016040528015613f01576020820181803683370190505b5090505b841561333257613f16600183614a84565b9150613f23600a86614b6c565b613f2e906030614a39565b60f81b818381518110613f4357613f43614bd8565b60200101906001600160f81b031916908160001a905350613f65600a86614a51565b9450613f05565b60006001613f79846120d6565b613f839190614a84565b600083815260076020526040902054909150808214613fd6576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b60085460009061401b90600190614a84565b6000838152600960205260408120546008805493945090928490811061404357614043614bd8565b90600052602060002001549050806008838154811061406457614064614bd8565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061409c5761409c614bc2565b6001900381819060005260206000200160009055905550505050565b60006140c3836120d6565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b60608247101561415d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610aec565b843b6141ab5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610aec565b600080866001600160a01b031685876040516141c79190614713565b60006040518083038185875af1925050503d8060008114614204576040519150601f19603f3d011682016040523d82523d6000602084013e614209565b606091505b5091509150614219828286614224565b979650505050505050565b60608315614233575081613130565b8251156142435782518084602001fd5b8160405162461bcd60e51b8152600401610aec9190614837565b82805461426990614aea565b90600052602060002090601f01602090048101928261428b57600085556142d1565b82601f106142a457805160ff19168380011785556142d1565b828001600101855582156142d1579182015b828111156142d15782518255916020019190600101906142b6565b506142dd929150614317565b5090565b5080546142ed90614aea565b6000825580601f106142fd575050565b601f016020900490600052602060002090810190611d4091905b5b808211156142dd5760008155600101614318565b60006001600160401b0383111561434557614345614bee565b60405161435c601f8501601f191660200182614b25565b80915083815284848401111561437157600080fd5b83836020830137600060208583010152509392505050565b600082601f83011261439a57600080fd5b6131308383356020850161432c565b6000602082840312156143bb57600080fd5b813561313081614ca9565b600080604083850312156143d957600080fd5b82356143e481614ca9565b915060208301356143f481614ca9565b809150509250929050565b60008060006060848603121561441457600080fd5b833561441f81614ca9565b9250602084013561442f81614ca9565b929592945050506040919091013590565b6000806000806080858703121561445657600080fd5b843561446181614ca9565b9350602085013561447181614ca9565b92506040850135915060608501356001600160401b0381111561449357600080fd5b8501601f810187136144a457600080fd5b6144b38782356020840161432c565b91505092959194509250565b600080604083850312156144d257600080fd5b82356144dd81614ca9565b915060208301356143f481614cbe565b6000806040838503121561450057600080fd5b823561450b81614ca9565b946020939093013593505050565b6000806020838503121561452c57600080fd5b82356001600160401b038082111561454357600080fd5b818501915085601f83011261455757600080fd5b81358181111561456657600080fd5b8660208260051b850101111561457b57600080fd5b60209290920196919550909350505050565b60006020828403121561459f57600080fd5b813561313081614cbe565b6000602082840312156145bc57600080fd5b815161313081614cbe565b6000602082840312156145d957600080fd5b813561313081614ccc565b6000602082840312156145f657600080fd5b815161313081614ccc565b6000806040838503121561461457600080fd5b82356002811061450b57600080fd5b60006020828403121561463557600080fd5b81356001600160401b0381111561464b57600080fd5b61333284828501614389565b60006020828403121561466957600080fd5b5035919050565b60006020828403121561468257600080fd5b5051919050565b6000806040838503121561469c57600080fd5b8235915060208301356001600160401b038111156146b957600080fd5b61126e85828601614389565b600080604083850312156146d857600080fd5b50508035926020909101359150565b600081518084526146ff816020860160208601614a9b565b601f01601f19169290920160200192915050565b60008251614725818460208701614a9b565b9190910192915050565b60008351614741818460208801614a9b565b835190830190614755818360208801614a9b565b01949350505050565b742330b4b632b2103a379039b2b7321022ba3432b91d60591b81526000825161478e816015850160208701614a9b565b9190910160150192915050565b878152866020820152848660408301376040940193840192909252606090811b6001600160601b0319169083015260748201526094019392505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613818908301846146e7565b604081016002841061482d57634e487b7160e01b600052602160045260246000fd5b9281526020015290565b60208152600061313060208301846146e7565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526026908201527f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060408201526573686172657360d01b606082015260800190565b6020808252602b908201527f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060408201526a191d59481c185e5b595b9d60aa1b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526012908201527110dbdb9d1c9858dd081a5cc81c185d5cd95960721b604082015260600190565b60208082526018908201527f43616e2774207061792061207a65726f20616464726573730000000000000000604082015260600190565b6020808252600990820152682737ba1030b236b4b760b91b604082015260600190565b60008219821115614a4c57614a4c614b80565b500190565b600082614a6057614a60614b96565b500490565b6000816000190483118215151615614a7f57614a7f614b80565b500290565b600082821015614a9657614a96614b80565b500390565b60005b83811015614ab6578181015183820152602001614a9e565b83811115611a665750506000910152565b60006001600160401b03821680614ae057614ae0614b80565b6000190192915050565b600181811c90821680614afe57607f821691505b60208210811415614b1f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8201601f191681016001600160401b0381118282101715614b4a57614b4a614bee565b6040525050565b6000600019821415614b6557614b65614b80565b5060010190565b600082614b7b57614b7b614b96565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d1115614c1d5760046000803e5060005160e01c5b90565b600060443d1015614c2e5790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715614c5d57505050505090565b8285019150815181811115614c755750505050505090565b843d8701016020828501011115614c8f5750505050505090565b614c9e60208286010187614b25565b509095945050505050565b6001600160a01b0381168114611d4057600080fd5b8015158114611d4057600080fd5b6001600160e01b031981168114611d4057600080fdfea2646970667358221220414d9951eb094e9f3eecc45ff7dcf1c7de317858d1ad8616b1355e70b4b69e2c64736f6c63430008070033

Deployed Bytecode Sourcemap

70375:15255:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65750:40;12812:10;65750:40;;;-1:-1:-1;;;;;11034:32:1;;;11016:51;;65780:9:0;11098:2:1;11083:18;;11076:34;10989:18;65750:40:0;;;;;;;70375:15255;;;;;74028:220;;;;;;;;;;-1:-1:-1;74028:220:0;;;;;:::i;:::-;;:::i;:::-;;;12058:14:1;;12051:22;12033:41;;12021:2;12006:18;74028:220:0;;;;;;;;75659:117;;;;;;;;;;-1:-1:-1;75659:117:0;;;;;:::i;:::-;;:::i;:::-;;35881:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;37440:221::-;;;;;;;;;;-1:-1:-1;37440:221:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;10566:32:1;;;10548:51;;10536:2;10521:18;37440:221:0;10402:203:1;77956:137:0;;;;;;;;;;-1:-1:-1;77956:137:0;;;;;:::i;:::-;;:::i;36963:411::-;;;;;;;;;;-1:-1:-1;36963:411:0;;;;;:::i;:::-;;:::i;80900:704::-;;;:::i;77082:201::-;;;;;;;;;;-1:-1:-1;77082:201:0;;;;;:::i;:::-;;:::i;50387:113::-;;;;;;;;;;-1:-1:-1;50475:10:0;:17;50387:113;;;29419:25:1;;;29407:2;29392:18;50387:113:0;29273:177:1;67639:633:0;;;;;;;;;;-1:-1:-1;67639:633:0;;;;;:::i;:::-;;:::i;38330:339::-;;;;;;;;;;-1:-1:-1;38330:339:0;;;;;:::i;:::-;;:::i;27054:321::-;;;;;;;;;;-1:-1:-1;27054:321:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;11034:32:1;;;11016:51;;11098:2;11083:18;;11076:34;;;;10989:18;27054:321:0;10834:282:1;50055:256:0;;;;;;;;;;-1:-1:-1;50055:256:0;;;;;:::i;:::-;;:::i;65984:91::-;;;;;;;;;;-1:-1:-1;66055:12:0;;65984:91;;75421:125;;;;;;;;;;;;;:::i;67113:135::-;;;;;;;;;;-1:-1:-1;67113:135:0;;;;;:::i;:::-;-1:-1:-1;;;;;67210:21:0;;;67183:7;67210:21;;;:14;:21;;;;;;;;:30;;;;;;;;;;;;;67113:135;79083:890;;;;;;:::i;:::-;;:::i;38740:185::-;;;;;;;;;;-1:-1:-1;38740:185:0;;;;;:::i;:::-;;:::i;74405:118::-;;;;;;;;;;-1:-1:-1;74405:118:0;;;;;:::i;:::-;;:::i;70886:38::-;;;;;;;;;;-1:-1:-1;70886:38:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;81695:604;;;;;;:::i;:::-;;:::i;68540:708::-;;;;;;;;;;-1:-1:-1;68540:708:0;;;;;:::i;:::-;;:::i;50577:233::-;;;;;;;;;;-1:-1:-1;50577:233:0;;;;;:::i;:::-;;:::i;76928:146::-;;;;;;;;;;-1:-1:-1;76928:146:0;;;;;:::i;:::-;;:::i;75003:406::-;;;;;;;;;;;;;:::i;78105:184::-;;;;;;;;;;-1:-1:-1;78105:184:0;;;;;:::i;:::-;;:::i;35575:239::-;;;;;;;;;;-1:-1:-1;35575:239:0;;;;;:::i;:::-;;:::i;75785:331::-;;;;;;;;;;-1:-1:-1;75785:331:0;;;;;:::i;:::-;;:::i;77599:345::-;;;;;;;;;;-1:-1:-1;77599:345:0;;;;;:::i;:::-;;:::i;35305:208::-;;;;;;;;;;-1:-1:-1;35305:208:0;;;;;:::i;:::-;;:::i;14538:94::-;;;;;;;;;;;;;:::i;74739:152::-;;;;;;;;;;-1:-1:-1;74739:152:0;;;;;:::i;:::-;;:::i;78301:222::-;;;;;;;;;;;;;:::i;67339:100::-;;;;;;;;;;-1:-1:-1;67339:100:0;;;;;:::i;:::-;;:::i;80429:281::-;;;;;;;;;;-1:-1:-1;80429:281:0;;;;;:::i;:::-;;:::i;13887:87::-;;;;;;;;;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;13887:87;;36050:104;;;;;;;;;;;;;:::i;66835:109::-;;;;;;;;;;-1:-1:-1;66835:109:0;;;;;:::i;:::-;-1:-1:-1;;;;;66918:18:0;66891:7;66918:18;;;:9;:18;;;;;;;66835:109;78621:348;;;;;;;;;;;;;:::i;37733:295::-;;;;;;;;;;-1:-1:-1;37733:295:0;;;;;:::i;:::-;;:::i;70841:38::-;;;;;;;;;;-1:-1:-1;70841:38:0;;;;;:::i;:::-;;;;;;;;;;;;;;38996:328;;;;;;;;;;-1:-1:-1;38996:328:0;;;;;:::i;:::-;;:::i;74639:92::-;;;;;;;;;;-1:-1:-1;74639:92:0;;;;;:::i;:::-;;:::i;77295:190::-;;;;;;;;;;-1:-1:-1;77295:190:0;;;;;:::i;:::-;;:::i;79985:432::-;;;;;;;;;;-1:-1:-1;79985:432:0;;;;;:::i;:::-;;:::i;66631:105::-;;;;;;;;;;-1:-1:-1;66631:105:0;;;;;:::i;:::-;-1:-1:-1;;;;;66712:16:0;66685:7;66712:16;;;:7;:16;;;;;;;66631:105;66421:119;;;;;;;;;;-1:-1:-1;66421:119:0;;;;;:::i;:::-;-1:-1:-1;;;;;66506:26:0;66479:7;66506:26;;;:19;:26;;;;;;;66421:119;70791:43;;;;;;;;;;-1:-1:-1;70791:43:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;66169:95;;;;;;;;;;-1:-1:-1;66242:14:0;;66169:95;;38099:164;;;;;;;;;;-1:-1:-1;38099:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;38220:25:0;;;38196:4;38220:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;38099:164;76125:337;;;;;;;;;;-1:-1:-1;76125:337:0;;;;;:::i;:::-;;:::i;14787:192::-;;;;;;;;;;-1:-1:-1;14787:192:0;;;;;:::i;:::-;;:::i;76496:199::-;;;;;;;;;;-1:-1:-1;76496:199:0;;;;;:::i;:::-;;:::i;74028:220::-;74180:4;74204:36;74228:11;74204:23;:36::i;:::-;74197:43;74028:220;-1:-1:-1;;74028:220:0:o;75659:117::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;;;;;;;;;75719:6:::1;:17:::0;;-1:-1:-1;;75719:17:0::1;::::0;::::1;;::::0;;::::1;::::0;;;75752:16:::1;::::0;12033:41:1;;;75752:16:0::1;::::0;12021:2:1;12006:18;75752:16:0::1;;;;;;;;75659:117:::0;:::o;35881:100::-;35935:13;35968:5;35961:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35881:100;:::o;37440:221::-;37516:7;37544:16;37552:7;37544;:16::i;:::-;37536:73;;;;-1:-1:-1;;;37536:73:0;;22316:2:1;37536:73:0;;;22298:21:1;22355:2;22335:18;;;22328:30;22394:34;22374:18;;;22367:62;-1:-1:-1;;;22445:18:1;;;22438:42;22497:19;;37536:73:0;22114:408:1;37536:73:0;-1:-1:-1;37629:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;37629:24:0;;37440:221::o;77956:137::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;78025:7:::1;:16:::0;;;78057:28:::1;::::0;29419:25:1;;;78057:28:0::1;::::0;29407:2:1;29392:18;78057:28:0::1;29273:177:1::0;36963:411:0;37044:13;37060:23;37075:7;37060:14;:23::i;:::-;37044:39;;37108:5;-1:-1:-1;;;;;37102:11:0;:2;-1:-1:-1;;;;;37102:11:0;;;37094:57;;;;-1:-1:-1;;;37094:57:0;;25043:2:1;37094:57:0;;;25025:21:1;25082:2;25062:18;;;25055:30;25121:34;25101:18;;;25094:62;-1:-1:-1;;;25172:18:1;;;25165:31;25213:19;;37094:57:0;24841:397:1;37094:57:0;12812:10;-1:-1:-1;;;;;37186:21:0;;;;:62;;-1:-1:-1;37211:37:0;37228:5;12812:10;38099:164;:::i;37211:37::-;37164:168;;;;-1:-1:-1;;;37164:168:0;;19533:2:1;37164:168:0;;;19515:21:1;19572:2;19552:18;;;19545:30;19611:34;19591:18;;;19584:62;19682:26;19662:18;;;19655:54;19726:19;;37164:168:0;19331:420:1;37164:168:0;37345:21;37354:2;37358:7;37345:8;:21::i;:::-;37033:341;36963:411;;:::o;80900:704::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;80963:6:::1;::::0;::::1;;80962:7;80954:38;;;;-1:-1:-1::0;;;80954:38:0::1;;;;;;;:::i;:::-;81003:12;:10;:12::i;:::-;81026:20;81049:35;81070:13;50475:10:::0;:17;;50387:113;81070:13:::1;81049:20;:35::i;:::-;81026:58:::0;-1:-1:-1;81108:16:0::1;81095:10;81135:462;81156:6;:13;81152:1;:17;81135:462;;;81191:12;81206:19;81216:1;81219:5;81206:9;:19::i;:::-;81191:34:::0;-1:-1:-1;81248:12:0;81240:42:::1;;;::::0;-1:-1:-1;;;81240:42:0;;26568:2:1;81240:42:0::1;::::0;::::1;26550:21:1::0;26607:2;26587:18;;;26580:30;-1:-1:-1;;;26626:18:1;;;26619:47;26683:18;;81240:42:0::1;26366:341:1::0;81240:42:0::1;81297:14;81314:16;81322:7;81314;:16::i;:::-;81297:33:::0;-1:-1:-1;;;;;;81353:20:0;::::1;81345:57;;;;-1:-1:-1::0;;;81345:57:0::1;;;;;;;:::i;:::-;81417:46;81429:6;70996:4;81439:6;81446:1;81439:9;;;;;;;;:::i;:::-;;;;;;;:22;;;;:::i;:::-;81417:3;:46::i;:::-;81505:24;::::0;-1:-1:-1;;;;;;7983:2:1;7979:15;;;7975:53;81505:24:0::1;::::0;::::1;7963:66:1::0;8045:12;;81505:24:0::1;;;;;;;;;;;;81495:35;;;;;;81490:41;;81484:5;:47;81478:53;;81551:34;81558:7;81567:6;81575;81582:1;81575:9;;;;;;;;:::i;:::-;;;;;;;81551:34;;;;;;;29657:25:1::0;;;-1:-1:-1;;;;;29718:32:1;;;;29713:2;29698:18;;29691:60;29782:2;29767:18;;29760:34;29645:2;29630:18;;29455:345;81551:34:0::1;;;;;;;;81176:421;;81171:3;;;;;:::i;:::-;;;;81135:462;;77082:201:::0;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;77181:17:::1;77189:8;77181:7;:17::i;:::-;77173:58;;;::::0;-1:-1:-1;;;77173:58:0;;24686:2:1;77173:58:0::1;::::0;::::1;24668:21:1::0;24725:2;24705:18;;;24698:30;24764;24744:18;;;24737:58;24812:18;;77173:58:0::1;24484:352:1::0;77173:58:0::1;77242:33;77255:8;77265:9;77242:12;:33::i;:::-;77082:201:::0;;:::o;67639:633::-;-1:-1:-1;;;;;67715:16:0;;67734:1;67715:16;;;:7;:16;;;;;;67707:71;;;;-1:-1:-1;;;67707:71:0;;;;;;;:::i;:::-;67791:21;67839:15;66242:14;;;66169:95;67839:15;67815:39;;:21;:39;:::i;:::-;67791:63;;67865:15;67883:58;67899:7;67908:13;67923:17;67932:7;-1:-1:-1;;;;;66918:18:0;66891:7;66918:18;;;:9;:18;;;;;;;66835:109;67923:17;67883:15;:58::i;:::-;67865:76;-1:-1:-1;67958:12:0;;67954:311;;-1:-1:-1;;;;;67987:18:0;;;;;;:9;:18;;;;;:29;;68009:7;;67987:18;:29;;68009:7;;67987:29;:::i;:::-;;;;;;;;68049:7;68031:14;;:25;;;;;;;:::i;:::-;;;;-1:-1:-1;68073:35:0;;-1:-1:-1;68091:7:0;68100;68073:17;:35::i;:::-;68128:33;;;-1:-1:-1;;;;;11034:32:1;;11016:51;;11098:2;11083:18;;11076:34;;;68128:33:0;;10989:18:1;68128:33:0;;;;;;;;37033:341;36963:411;;:::o;67954:311::-;68199:54;;;;;;:::i;38330:339::-;38525:41;12812:10;38558:7;38525:18;:41::i;:::-;38517:103;;;;-1:-1:-1;;;38517:103:0;;;;;;;:::i;:::-;38633:28;38643:4;38649:2;38653:7;38633:9;:28::i;27054:321::-;27224:41;;;;;;;;;27255:10;27224:41;-1:-1:-1;;;;;27224:41:0;;;;;-1:-1:-1;;;27224:41:0;;;;;;;;;;;;;-1:-1:-1;;27362:5:0;;27334:24;;:5;:24;:::i;:::-;27333:34;;;;:::i;:::-;27317:50;;27213:162;27054:321;;;;;:::o;50055:256::-;50152:7;50188:23;50205:5;50188:16;:23::i;:::-;50180:5;:31;50172:87;;;;-1:-1:-1;;;50172:87:0;;12929:2:1;50172:87:0;;;12911:21:1;12968:2;12948:18;;;12941:30;13007:34;12987:18;;;12980:62;-1:-1:-1;;;13058:18:1;;;13051:41;13109:19;;50172:87:0;12727:407:1;50172:87:0;-1:-1:-1;;;;;;50277:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;50055:256::o;75421:125::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;75471:12:::1;:10;:12::i;:::-;75494:44;75506:7;13960:6:::0;;-1:-1:-1;;;;;13960:6:0;;13887:87;75506:7:::1;75516:21;75494:3;:44::i;:::-;75421:125::o:0;79083:890::-;79150:11;79164:13;50475:10;:17;;50387:113;79164:13;79150:27;;79188:15;79221:10;;79207;:8;:10::i;:::-;79252:6;;79207:24;;;-1:-1:-1;79252:6:0;;79251:7;79243:38;;;;-1:-1:-1;;;79243:38:0;;;;;;;:::i;:::-;79309:1;79300:6;:10;79292:37;;;;-1:-1:-1;;;79292:37:0;;21194:2:1;79292:37:0;;;21176:21:1;21233:2;21213:18;;;21206:30;-1:-1:-1;;;21252:18:1;;;21245:44;21306:18;;79292:37:0;20992:338:1;79292:37:0;79358:7;;79348:6;:17;;79340:53;;;;-1:-1:-1;;;79340:53:0;;28433:2:1;79340:53:0;;;28415:21:1;28472:2;28452:18;;;28445:30;-1:-1:-1;;;28491:18:1;;;28484:53;28554:18;;79340:53:0;28231:347:1;79340:53:0;79431:9;;79412:15;79421:6;79412;:15;:::i;:::-;:28;;79404:59;;;;-1:-1:-1;;;79404:59:0;;26221:2:1;79404:59:0;;;26203:21:1;26260:2;26240:18;;;26233:30;-1:-1:-1;;;26279:18:1;;;26272:48;26337:18;;79404:59:0;26019:342:1;79404:59:0;79485:10;79478:18;;;;:6;:18;;;;;;;;:26;;:18;:26;79474:304;;79525:10;79521:152;;;79587:24;;-1:-1:-1;;;;;79564:10:0;;;;;;:6;:10;;;;;;:19;;79577:6;;79564:19;:::i;:::-;:47;;79556:101;;;;-1:-1:-1;;;79556:101:0;;23860:2:1;79556:101:0;;;23842:21:1;23899:2;23879:18;;;23872:30;23938:34;23918:18;;;23911:62;-1:-1:-1;;;23989:18:1;;;23982:39;24038:19;;79556:101:0;23658:405:1;79556:101:0;79721:9;79695:22;79710:6;79695:10;:8;:10::i;:::-;:14;;:22::i;:::-;:35;79687:79;;;;-1:-1:-1;;;79687:79:0;;16800:2:1;79687:79:0;;;16782:21:1;16839:2;16819:18;;;16812:30;16878:33;16858:18;;;16851:61;16929:18;;79687:79:0;16598:355:1;79687:79:0;79802:1;79788:178;79810:6;79805:1;:11;79788:178;;79838:25;79848:2;79852:10;79861:1;79852:6;:10;:::i;:::-;79838:9;:25::i;:::-;79881:10;79878:77;;;-1:-1:-1;;;;;79925:10:0;;;;;;:6;:10;;;;;;:14;;79938:1;79925:14;:::i;:::-;-1:-1:-1;;;;;79912:10:0;;;;;;:6;:10;;;;;:27;79878:77;79818:3;;;;:::i;:::-;;;;79788:178;;;;79139:834;;79083:890;;:::o;38740:185::-;38878:39;38895:4;38901:2;38905:7;38878:39;;;;;;;;;;;;:16;:39::i;74405:118::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;74464:15:::1;74470:8;74464:5;:15::i;:::-;74514:1;74502:9;;:13;;;;:::i;:::-;74490:9;:25:::0;-1:-1:-1;74405:118:0:o;81695:604::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;81776:6:::1;::::0;::::1;;81775:7;81767:38;;;;-1:-1:-1::0;;;81767:38:0::1;;;;;;;:::i;:::-;81816:12;:10;:12::i;:::-;81866:32;::::0;;-1:-1:-1;;;;;;81883:14:0::1;7983:2:1::0;7979:15;;;7975:53;;81866:32:0::1;::::0;;::::1;7963:66:1::0;;;;81866:32:0;;;;;;;;;8045:12:1;;;81866:32:0;;81856:43;;;;::::1;::::0;81956:10:::1;7979:15:1::0;;;7975:53;;;81939:28:0;;;7963:66:1;81939:28:0;;;;;;;;;8045:12:1;;;;81939:28:0;;;81929:39;;;::::1;::::0;81839:9:::1;81995:22;81856:43:::0;81929:39;81995:9:::1;:22::i;:::-;81980:37:::0;-1:-1:-1;82036:12:0;82028:42:::1;;;::::0;-1:-1:-1;;;82028:42:0;;26568:2:1;82028:42:0::1;::::0;::::1;26550:21:1::0;26607:2;26587:18;;;26580:30;-1:-1:-1;;;26626:18:1;;;26619:47;26683:18;;82028:42:0::1;26366:341:1::0;82028:42:0::1;82081:14;82098:16;82106:7;82098;:16::i;:::-;82081:33:::0;-1:-1:-1;;;;;;82133:20:0;::::1;82125:57;;;;-1:-1:-1::0;;;82125:57:0::1;;;;;;;:::i;:::-;82193:47;82205:6:::0;82215:23:::1;70996:4;82215:10:::0;:23:::1;:::i;82193:47::-;82256:35;::::0;;29657:25:1;;;-1:-1:-1;;;;;29718:32:1;;29713:2;29698:18;;29691:60;29767:18;;;29760:34;;;82256:35:0::1;::::0;29645:2:1;29630:18;82256:35:0::1;;;;;;;81756:543;;;;81695:604:::0;:::o;68540:708::-;-1:-1:-1;;;;;68622:16:0;;68641:1;68622:16;;;:7;:16;;;;;;68614:71;;;;-1:-1:-1;;;68614:71:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;66506:26:0;;68698:21;66506:26;;;:19;:26;;;;;;68722:30;;-1:-1:-1;;;68722:30:0;;68746:4;68722:30;;;10548:51:1;-1:-1:-1;;;;;68722:15:0;;;;;10521:18:1;;68722:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;;;;:::i;:::-;68698:77;;68786:15;68804:65;68820:7;68829:13;68844:24;68853:5;68860:7;-1:-1:-1;;;;;67210:21:0;;;67183:7;67210:21;;;:14;:21;;;;;;;;:30;;;;;;;;;;;;;67113:135;68804:65;68786:83;-1:-1:-1;68886:12:0;;68882:359;;-1:-1:-1;;;;;68915:21:0;;;;;;;:14;:21;;;;;;;;:30;;;;;;;;;;;:41;;68949:7;;68915:21;:41;;68949:7;;68915:41;:::i;:::-;;;;-1:-1:-1;;;;;;;68971:26:0;;;;;;:19;:26;;;;;:37;;69001:7;;68971:26;:37;;69001:7;;68971:37;:::i;:::-;;;;-1:-1:-1;69025:47:0;;-1:-1:-1;69048:5:0;69055:7;69064;69025:22;:47::i;:::-;69092:45;;;-1:-1:-1;;;;;11034:32:1;;;11016:51;;11098:2;11083:18;;11076:34;;;69092:45:0;;;;;10989:18:1;69092:45:0;;;;;;;68882:359;;;69175:54;;;;;;:::i;:::-;;;;;;;;68882:359;68603:645;;68540:708;;:::o;50577:233::-;50652:7;50688:30;50475:10;:17;;50387:113;50688:30;50680:5;:38;50672:95;;;;-1:-1:-1;;;50672:95:0;;26914:2:1;50672:95:0;;;26896:21:1;26953:2;26933:18;;;26926:30;26992:34;26972:18;;;26965:62;-1:-1:-1;;;27043:18:1;;;27036:42;27095:19;;50672:95:0;26712:408:1;50672:95:0;50785:10;50796:5;50785:17;;;;;;;;:::i;:::-;;;;;;;;;50778:24;;50577:233;;;:::o;76928:146::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;77004:20;;::::1;::::0;:7:::1;::::0;:20:::1;::::0;::::1;::::0;::::1;:::i;:::-;;77040:26;77055:10;77040:26;;;;;;:::i;75003:406::-:0;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;75058:6:::1;75053:349;75074:5;:12:::0;75070:16;::::1;75053:349;;;75108:14;75125:5;75131:1;75125:8;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;75152:29:::1;::::0;-1:-1:-1;;;75152:29:0;;-1:-1:-1;;;;;75125:8:0;;::::1;75152:29;::::0;::::1;10548:51:1::0;;;75125:8:0;-1:-1:-1;75152:4:0::1;::::0;:12:::1;::::0;10521:18:1;;75152:29:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;75148:243;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;75262:17;75266:12;75262:17;;;;;;:::i;:::-;;;;;;;;75198:97;75148:243;;;;;;::::0;;;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75352:23;75363:10;75352:23;;;;;;:::i;75148:243::-;-1:-1:-1::0;75088:3:0;::::1;::::0;::::1;:::i;:::-;;;;75053:349;;;;75003:406::o:0;78105:184::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;78190:24:::1;:38:::0;;;78244:37:::1;::::0;29419:25:1;;;78244:37:0::1;::::0;29407:2:1;29392:18;78244:37:0::1;29273:177:1::0;35575:239:0;35647:7;35683:16;;;:7;:16;;;;;;-1:-1:-1;;;;;35683:16:0;35718:19;35710:73;;;;-1:-1:-1;;;35710:73:0;;20369:2:1;35710:73:0;;;20351:21:1;20408:2;20388:18;;;20381:30;20447:34;20427:18;;;20420:62;-1:-1:-1;;;20498:18:1;;;20491:39;20547:19;;35710:73:0;20167:405:1;75785:331:0;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;75875:6:::1;75870:239;75887:16:::0;;::::1;75870:239;;;75953:1;75933:5:::0;;75939:1;75933:8;;::::1;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;75933:22:0::1;;;75925:59;;;::::0;-1:-1:-1;;;75925:59:0;;14099:2:1;75925:59:0::1;::::0;::::1;14081:21:1::0;14138:2;14118:18;;;14111:30;14177:26;14157:18;;;14150:54;14221:18;;75925:59:0::1;13897:348:1::0;75925:59:0::1;76003:11;:21;76015:5;;76021:1;76015:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;76003:21:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;76003:21:0;;::::1;;75999:99;;76078:4;76054:11;:21;76066:5;;76072:1;76066:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;76054:21:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;76054:21:0;:28;;-1:-1:-1;;76054:28:0::1;::::0;::::1;;::::0;;;::::1;::::0;;75999:99:::1;75905:3:::0;::::1;::::0;::::1;:::i;:::-;;;;75870:239;;77599:345:::0;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;77696:1:::1;77688:5;:9;77680:32;;;::::0;-1:-1:-1;;;77680:32:0;;13341:2:1;77680:32:0::1;::::0;::::1;13323:21:1::0;13380:2;13360:18;;;13353:30;-1:-1:-1;;;13399:18:1;;;13392:40;13449:18;;77680:32:0::1;13139:334:1::0;77680:32:0::1;77740:15;77727:9;:28;;;;;;;;:::i;:::-;;77723:162;;;77772:10;:18:::0;;;77723:162:::1;;;77825:14;77812:9;:27;;;;;;;;:::i;:::-;;77808:77;;;77856:9;:17:::0;;;77808:77:::1;77900:36;77919:9;77930:5;77900:36;;;;;;;:::i;:::-;;;;;;;;77599:345:::0;;:::o;35305:208::-;35377:7;-1:-1:-1;;;;;35405:19:0;;35397:74;;;;-1:-1:-1;;;35397:74:0;;19958:2:1;35397:74:0;;;19940:21:1;19997:2;19977:18;;;19970:30;20036:34;20016:18;;;20009:62;-1:-1:-1;;;20087:18:1;;;20080:40;20137:19;;35397:74:0;19756:406:1;35397:74:0;-1:-1:-1;;;;;;35489:16:0;;;;;:9;:16;;;;;;;35305:208::o;14538:94::-;13960:6;;-1:-1:-1;;;;;13960:6:0;12812:10;14107:23;14099:68;;;;-1:-1:-1;;;14099:68:0;;;;;;;:::i;:::-;14603:21:::1;14621:1;14603:9;:21::i;74739:152::-:0;13960:6;;-1:-1:-1;;;;;13960:6:0;12812:10;14107:23;14099:68;;;;-1:-1:-1;;;14099:68:0;;;;;;;:::i;:::-;13960:6;;-1:-1:-1;;;;;74813:15:0;;::::1;13960:6:::0;;74813:15:::1;;74805:47;;;::::0;-1:-1:-1;;;74805:47:0;;27738:2:1;74805:47:0::1;::::0;::::1;27720:21:1::0;27777:2;27757:18;;;27750:30;-1:-1:-1;;;27796:18:1;;;27789:49;27855:18;;74805:47:0::1;27536:343:1::0;74805:47:0::1;-1:-1:-1::0;;;;;74863:12:0::1;74878:5;74863:12:::0;;;:6:::1;:12;::::0;;;;:20;;-1:-1:-1;;74863:20:0::1;::::0;;74739:152::o;78301:222::-;78366:5;:15;78341:4;;78366:19;;;;:74;;-1:-1:-1;78425:5:0;:15;78406;:34;;78366:74;:148;;;;-1:-1:-1;78499:14:0;;:5;78481:15;:32;;78499:14;78481:32;:::i;:::-;78461:15;:53;;78366:148;78358:157;;78301:222;:::o;67339:100::-;67390:7;67417;67425:5;67417:14;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;67417:14:0;;67339:100;-1:-1:-1;;67339:100:0:o;80429:281::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;80511:6:::1;::::0;::::1;;80510:7;80502:38;;;;-1:-1:-1::0;;;80502:38:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;80559:16:0;::::1;80551:60;;;::::0;-1:-1:-1;;;80551:60:0;;23500:2:1;80551:60:0::1;::::0;::::1;23482:21:1::0;23539:2;23519:18;;;23512:30;23578:33;23558:18;;;23551:61;23629:18;;80551:60:0::1;23298:355:1::0;80551:60:0::1;80622:41;80639:10;80651:2;80655:7;80622:16;:41::i;:::-;80679:23;::::0;;-1:-1:-1;;;;;11034:32:1;;11016:51;;11098:2;11083:18;;11076:34;;;80679:23:0::1;::::0;10989:18:1;80679:23:0::1;10834:282:1::0;36050:104:0;36106:13;36139:7;36132:14;;;;;:::i;78621:348::-;78692:9;;78723:10;78662:4;78716:18;;;:6;:18;;;;;;78662:4;;78692:9;78716:18;;:26;;:18;:26;78712:227;;;-1:-1:-1;78758:1:0;78956:5;78621:348;-1:-1:-1;78621:348:0:o;78712:227::-;78776:9;:7;:9::i;:::-;:44;;;-1:-1:-1;78801:10:0;78789:23;;;;:11;:23;;;;;;;;:31;;:23;:31;78776:44;78775:108;;;;-1:-1:-1;78859:24:0;;78845:10;78838:18;;;;:6;:18;;;;;;:45;78775:108;78771:168;;;-1:-1:-1;78917:10:0;;78771:168;78956:5;78621:348;-1:-1:-1;78621:348:0:o;37733:295::-;-1:-1:-1;;;;;37836:24:0;;12812:10;37836:24;;37828:62;;;;-1:-1:-1;;;37828:62:0;;16446:2:1;37828:62:0;;;16428:21:1;16485:2;16465:18;;;16458:30;16524:27;16504:18;;;16497:55;16569:18;;37828:62:0;16244:349:1;37828:62:0;12812:10;37903:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;37903:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;37903:53:0;;;;;;;;;;37972:48;;12033:41:1;;;37903:42:0;;12812:10;37972:48;;12006:18:1;37972:48:0;;;;;;;37733:295;;:::o;38996:328::-;39171:41;12812:10;39204:7;39171:18;:41::i;:::-;39163:103;;;;-1:-1:-1;;;39163:103:0;;;;;;;:::i;:::-;39277:39;39291:4;39297:2;39301:7;39310:5;39277:13;:39::i;74639:92::-;13960:6;;-1:-1:-1;;;;;13960:6:0;12812:10;14107:23;14099:68;;;;-1:-1:-1;;;14099:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;74704:12:0::1;;::::0;;;:6:::1;:12;::::0;;;;:19;;-1:-1:-1;;74704:19:0::1;74719:4;74704:19;::::0;;74639:92::o;77295:190::-;77420:13;77453:24;77468:8;77453:14;:24::i;79985:432::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;80054:11:::1;80068:13;50475:10:::0;:17;;50387:113;80068:13:::1;80101:6;::::0;80054:27;;-1:-1:-1;80101:6:0::1;;80100:7;80092:38;;;;-1:-1:-1::0;;;80092:38:0::1;;;;;;;:::i;:::-;80158:1;80149:6;:10;80141:37;;;::::0;-1:-1:-1;;;80141:37:0;;21194:2:1;80141:37:0::1;::::0;::::1;21176:21:1::0;21233:2;21213:18;;;21206:30;-1:-1:-1;;;21252:18:1;;;21245:44;21306:18;;80141:37:0::1;20992:338:1::0;80141:37:0::1;80207:7;;80197:6;:17;;80189:53;;;::::0;-1:-1:-1;;;80189:53:0;;28433:2:1;80189:53:0::1;::::0;::::1;28415:21:1::0;28472:2;28452:18;;;28445:30;-1:-1:-1;;;28491:18:1;;;28484:53;28554:18;;80189:53:0::1;28231:347:1::0;80189:53:0::1;80280:9;::::0;80261:15:::1;80270:6:::0;80261;:15:::1;:::i;:::-;:28;;80253:59;;;::::0;-1:-1:-1;;;80253:59:0;;26221:2:1;80253:59:0::1;::::0;::::1;26203:21:1::0;26260:2;26240:18;;;26233:30;-1:-1:-1;;;26279:18:1;;;26272:48;26337:18;;80253:59:0::1;26019:342:1::0;80253:59:0::1;80337:1;80323:87;80345:6;80340:1;:11;80323:87;;80373:25;80383:2:::0;80387:10:::1;80396:1:::0;80387:6;:10:::1;:::i;80373:25::-;80353:3:::0;::::1;::::0;::::1;:::i;:::-;;;;80323:87;;76125:337:::0;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;76218:6:::1;76213:242;76230:16:::0;;::::1;76213:242;;;76296:1;76276:5:::0;;76282:1;76276:8;;::::1;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;76276:22:0::1;;;76268:62;;;::::0;-1:-1:-1;;;76268:62:0;;19177:2:1;76268:62:0::1;::::0;::::1;19159:21:1::0;19216:2;19196:18;;;19189:30;19255:29;19235:18;;;19228:57;19302:18;;76268:62:0::1;18975:351:1::0;76268:62:0::1;76349:11;:21;76361:5;;76367:1;76361:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;76349:21:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;76349:21:0;;::::1;;:29;;:21:::0;:29:::1;76345:99;;;76423:5;76399:11;:21;76411:5;;76417:1;76411:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;76399:21:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;76399:21:0;:29;;-1:-1:-1;;76399:29:0::1;::::0;::::1;;::::0;;;::::1;::::0;;76345:99:::1;76248:3:::0;::::1;::::0;::::1;:::i;:::-;;;;76213:242;;14787:192:::0;13960:6;;-1:-1:-1;;;;;13960:6:0;12812:10;14107:23;14099:68;;;;-1:-1:-1;;;14099:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;14876:22:0;::::1;14868:73;;;::::0;-1:-1:-1;;;14868:73:0;;14452:2:1;14868:73:0::1;::::0;::::1;14434:21:1::0;14491:2;14471:18;;;14464:30;14530:34;14510:18;;;14503:62;-1:-1:-1;;;14581:18:1;;;14574:36;14627:19;;14868:73:0::1;14250:402:1::0;14868:73:0::1;14952:19;14962:8;14952:9;:19::i;76496:199::-:0;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;76612:26:::1;::::0;;;;::::1;::::0;;76578:15:::1;76612:26:::0;;;::::1;::::0;;::::1;::::0;;;76604:5:::1;:34:::0;;;;;;;76654:33;;29979:25:1;;;30020:18;;;30013:34;;;76578:15:0;76654:33:::1;::::0;29952:18:1;76654:33:0::1;29805:248:1::0;26061:283:0;26191:4;-1:-1:-1;;;;;;26233:50:0;;-1:-1:-1;;;26233:50:0;;:103;;;26300:36;26324:11;26300:23;:36::i;40834:127::-;40899:4;40923:16;;;:7;:16;;;;;;-1:-1:-1;;;;;40923:16:0;:30;;;40834:127::o;44816:174::-;44891:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;44891:29:0;-1:-1:-1;;;;;44891:29:0;;;;;;;;:24;;44945:23;44891:24;44945:14;:23::i;:::-;-1:-1:-1;;;;;44936:46:0;;;;;;;;;;;44816:174;;:::o;83101:1086::-;83172:13;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;83248:14:::1;::::0;;83259:2:::1;83248:14:::0;;;;;::::1;::::0;;;83202:10:::1;::::0;;;83248:14;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;83248:14:0::1;83227:35;;83278:6;83273:99;83294:1;83290;:5;83273:99;;;83355:5;83317:12;:35;83330:7;83338:1;83330:10;;;;;;;:::i;:::-;;:21:::0;-1:-1:-1;;;83330:21:0;::::1;-1:-1:-1::0;;;;;83330:21:0::1;83317:35:::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;83317:35:0;:43;;-1:-1:-1;;83317:43:0::1;::::0;::::1;;::::0;;;::::1;::::0;;83297:3;::::1;::::0;::::1;:::i;:::-;;;;83273:99;;;;83387:6;83382:634;83403:14;83399:1;:18;83382:634;;;83463:6;83443:7;83451:1;83443:10;;;;;;;:::i;:::-;;:17:::0;-1:-1:-1;;;;;83443:17:0::1;:26;83439:72;;;83490:5;;83439:72;83551:6;83530:7;83538:1;83530:10;;;;;;;:::i;:::-;;:17:::0;-1:-1:-1;;;;;83530:17:0::1;:27;::::0;::::1;::::0;83529:79:::1;;;83606:1;83580:7;83588:1;83580:10;;;;;;;:::i;:::-;;:23:::0;-1:-1:-1;;;83580:23:0;::::1;-1:-1:-1::0;;;;;83580:23:0::1;:27;83529:79;:136;;;;;83630:12;:35;83643:7;83651:1;83643:10;;;;;;;:::i;:::-;;:21:::0;-1:-1:-1;;;83643:21:0;::::1;-1:-1:-1::0;;;;;83643:21:0::1;83630:35:::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;83630:35:0;;::::1;;83629:36;83529:136;83525:480;;;83691:6;83686:243;83707:59;83716:7;83724:1;83716:10;;;;;;;:::i;:::-;;:24:::0;-1:-1:-1;;;83716:24:0;::::1;-1:-1:-1::0;;;;;83716:24:0::1;83742:7;83750:1:::0;83742:10:::1;::::0;::::1;;;;;:::i;:::-;;:23:::0;-1:-1:-1;;;83742:23:0;::::1;-1:-1:-1::0;;;;;83742:23:0::1;83707:8;:59::i;:::-;83703:1;:63;83686:243;;;83796:7;83804:1;83796:10;;;;;;;:::i;:::-;;:25:::0;;-1:-1:-1;;;83796:25:0;::::1;-1:-1:-1::0;;;;;83796:25:0::1;::::0;:23:::1;:25;::::0;::::1;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;83796:25:0::1;;;;;-1:-1:-1::0;;;;;83796:25:0::1;;;;;;;83858:7;83866:1;83858:10;;;;;;;:::i;:::-;;:21:::0;83844:11;;-1:-1:-1;;;83858:21:0;;::::1;-1:-1:-1::0;;;;;83858:21:0::1;::::0;83844:11;;83849:5;;83844:11;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;:35;83902:7;::::1;::::0;::::1;:::i;:::-;;;;83768:3;;;;;:::i;:::-;;;;83686:243;;;;83985:4;83947:12;:35;83960:7;83968:1;83960:10;;;;;;;:::i;:::-;;:21:::0;-1:-1:-1;;;83960:21:0;::::1;-1:-1:-1::0;;;;;83960:21:0::1;83947:35:::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;83947:35:0;:42;;-1:-1:-1;;83947:42:0::1;::::0;::::1;;::::0;;;::::1;::::0;;83525:480:::1;83419:3:::0;::::1;::::0;::::1;:::i;:::-;;;;83382:634;;;;84026:20;84060:5;-1:-1:-1::0;;;;;84049:17:0::1;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;84049:17:0::1;;84026:40;;84082:6;84077:79;84098:5;84094:1;:9;84077:79;;;84137:4;84142:1;84137:7;;;;;;;;:::i;:::-;;;;;;;84125:6;84132:1;84125:9;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;:19;84105:3;::::1;::::0;::::1;:::i;:::-;;;;84077:79;;;-1:-1:-1::0;84173:6:0;83101:1086;-1:-1:-1;;;;83101:1086:0:o;84228:325::-;84302:4;72810;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;84319:11:::1;84333:13;50475:10:::0;:17;;50387:113;84333:13:::1;84319:27:::0;-1:-1:-1;84361:10:0;;84357:170:::1;;84388:12;84403:32;84415:6;84423:4;84429:5;84403:11;:32::i;:::-;84388:47:::0;-1:-1:-1;84454:11:0;;84450:66:::1;;84493:7:::0;-1:-1:-1;84486:14:0::1;::::0;-1:-1:-1;84486:14:0::1;84450:66;84373:154;84357:170;-1:-1:-1::0;84544:1:0::1;::::0;84228:325;-1:-1:-1;;;84228:325:0:o;84603:460::-;72810:4;12812:10;72802:29;;:56;;-1:-1:-1;13960:6:0;;-1:-1:-1;;;;;13960:6:0;12812:10;72835:23;72802:56;:78;;;-1:-1:-1;72869:10:0;72862:18;;;;:6;:18;;;;;;;;72802:78;72794:100;;;;-1:-1:-1;;;72794:100:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;84687:16:0;::::1;84679:53;;;;-1:-1:-1::0;;;84679:53:0::1;;;;;;;:::i;:::-;84776:6;84751:21;:31;;84743:93;;;::::0;-1:-1:-1;;;84743:93:0;;15216:2:1;84743:93:0::1;::::0;::::1;15198:21:1::0;15255:2;15235:18;;;15228:30;15294:34;15274:18;;;15267:62;-1:-1:-1;;;15345:18:1;;;15338:47;15402:19;;84743:93:0::1;15014:413:1::0;84743:93:0::1;84848:9;84859:17:::0;84880:2:::1;-1:-1:-1::0;;;;;84880:7:0::1;84895:6;84880:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84847:59;;;;84921:4;84917:58;;;84942:21;84956:6;84942:13;:21::i;:::-;84993:4;85048;85006:47;;;;;;;;:::i;:::-;;;;;;;;;;;;;84985:70;;;;;-1:-1:-1::0;;;84985:70:0::1;;;;;;;;:::i;48241:217::-:0;48341:16;48349:7;48341;:16::i;:::-;48333:75;;;;-1:-1:-1;;;48333:75:0;;20779:2:1;48333:75:0;;;20761:21:1;20818:2;20798:18;;;20791:30;20857:34;20837:18;;;20830:62;-1:-1:-1;;;20908:18:1;;;20901:44;20962:19;;48333:75:0;20577:410:1;48333:75:0;48419:19;;;;:10;:19;;;;;;;;:31;;;;;;;;:::i;69426:248::-;69636:12;;-1:-1:-1;;;;;69616:16:0;;69572:7;69616:16;;;:7;:16;;;;;;69572:7;;69651:15;;69600:32;;:13;:32;:::i;:::-;69599:49;;;;:::i;:::-;:67;;;;:::i;:::-;69592:74;;69426:248;;;;;;:::o;17199:317::-;17314:6;17289:21;:31;;17281:73;;;;-1:-1:-1;;;17281:73:0;;17587:2:1;17281:73:0;;;17569:21:1;17626:2;17606:18;;;17599:30;17665:31;17645:18;;;17638:59;17714:18;;17281:73:0;17385:353:1;17281:73:0;17368:12;17386:9;-1:-1:-1;;;;;17386:14:0;17408:6;17386:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17367:52;;;17438:7;17430:78;;;;-1:-1:-1;;;17430:78:0;;17160:2:1;17430:78:0;;;17142:21:1;17199:2;17179:18;;;17172:30;17238:34;17218:18;;;17211:62;17309:28;17289:18;;;17282:56;17355:19;;17430:78:0;16958:422:1;41128:348:0;41221:4;41246:16;41254:7;41246;:16::i;:::-;41238:73;;;;-1:-1:-1;;;41238:73:0;;18352:2:1;41238:73:0;;;18334:21:1;18391:2;18371:18;;;18364:30;18430:34;18410:18;;;18403:62;-1:-1:-1;;;18481:18:1;;;18474:42;18533:19;;41238:73:0;18150:408:1;41238:73:0;41322:13;41338:23;41353:7;41338:14;:23::i;:::-;41322:39;;41391:5;-1:-1:-1;;;;;41380:16:0;:7;-1:-1:-1;;;;;41380:16:0;;:51;;;;41424:7;-1:-1:-1;;;;;41400:31:0;:20;41412:7;41400:11;:20::i;:::-;-1:-1:-1;;;;;41400:31:0;;41380:51;:87;;;-1:-1:-1;;;;;;38220:25:0;;;38196:4;38220:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;41435:32;41372:96;41128:348;-1:-1:-1;;;;41128:348:0:o;44120:578::-;44279:4;-1:-1:-1;;;;;44252:31:0;:23;44267:7;44252:14;:23::i;:::-;-1:-1:-1;;;;;44252:31:0;;44244:85;;;;-1:-1:-1;;;44244:85:0;;23090:2:1;44244:85:0;;;23072:21:1;23129:2;23109:18;;;23102:30;23168:34;23148:18;;;23141:62;-1:-1:-1;;;23219:18:1;;;23212:39;23268:19;;44244:85:0;22888:405:1;44244:85:0;-1:-1:-1;;;;;44348:16:0;;44340:65;;;;-1:-1:-1;;;44340:65:0;;16041:2:1;44340:65:0;;;16023:21:1;16080:2;16060:18;;;16053:30;16119:34;16099:18;;;16092:62;-1:-1:-1;;;16170:18:1;;;16163:34;16214:19;;44340:65:0;15839:400:1;44340:65:0;44418:39;44439:4;44445:2;44449:7;44418:20;:39::i;:::-;44522:29;44539:1;44543:7;44522:8;:29::i;:::-;-1:-1:-1;;;;;44564:15:0;;;;;;:9;:15;;;;;:20;;44583:1;;44564:15;:20;;44583:1;;44564:20;:::i;:::-;;;;-1:-1:-1;;;;;;;44595:13:0;;;;;;:9;:13;;;;;:18;;44612:1;;44595:13;:18;;44612:1;;44595:18;:::i;:::-;;;;-1:-1:-1;;44624:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;44624:21:0;-1:-1:-1;;;;;44624:21:0;;;;;;;;;44663:27;;44624:16;;44663:27;;;;;;;44120:578;;;:::o;4201:98::-;4259:7;4286:5;4290:1;4286;:5;:::i;41818:110::-;41894:26;41904:2;41908:7;41894:26;;;;;;;;;;;;:9;:26::i;74260:133::-;74364:21;74376:8;74364:11;:21::i;59230:211::-;59374:58;;;-1:-1:-1;;;;;11034:32:1;;59374:58:0;;;11016:51:1;11083:18;;;;11076:34;;;59374:58:0;;;;;;;;;;10989:18:1;;;;59374:58:0;;;;;;;;-1:-1:-1;;;;;59374:58:0;-1:-1:-1;;;59374:58:0;;;59347:86;;59367:5;;59347:19;:86::i;14987:173::-;15062:6;;;-1:-1:-1;;;;;15079:17:0;;;-1:-1:-1;;;;;;15079:17:0;;;;;;;15112:40;;15062:6;;;15079:17;15062:6;;15112:40;;15043:16;;15112:40;15032:128;14987:173;:::o;40206:315::-;40363:28;40373:4;40379:2;40383:7;40363:9;:28::i;:::-;40410:48;40433:4;40439:2;40443:7;40452:5;40410:22;:48::i;:::-;40402:111;;;;-1:-1:-1;;;40402:111:0;;;;;;;:::i;47406:679::-;47479:13;47513:16;47521:7;47513;:16::i;:::-;47505:78;;;;-1:-1:-1;;;47505:78:0;;21898:2:1;47505:78:0;;;21880:21:1;21937:2;21917:18;;;21910:30;21976:34;21956:18;;;21949:62;-1:-1:-1;;;22027:18:1;;;22020:47;22084:19;;47505:78:0;21696:413:1;47505:78:0;47596:23;47622:19;;;:10;:19;;;;;47596:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47652:18;47673:10;:8;:10::i;:::-;47652:31;;47765:4;47759:18;47781:1;47759:23;47755:72;;;-1:-1:-1;47806:9:0;47406:679;-1:-1:-1;;47406:679:0:o;47755:72::-;47931:23;;:27;47927:108;;48006:4;48012:9;47989:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;47975:48;;;;47406:679;;;:::o;47927:108::-;48054:23;48069:7;48054:14;:23::i;49747:224::-;49849:4;-1:-1:-1;;;;;;49873:50:0;;-1:-1:-1;;;49873:50:0;;:90;;;49927:36;49951:11;49927:23;:36::i;8004:106::-;8062:7;8093:1;8089;:5;:13;;8101:1;8089:13;;;-1:-1:-1;8097:1:0;;8004:106;-1:-1:-1;8004:106:0:o;85105:522::-;85181:4;;85217:14;85230:1;85217:12;:14;:::i;:::-;85198:33;-1:-1:-1;85260:10:0;85267:3;85260:4;:10;:::i;:::-;85246:12;:25;85242:95;;;85314:10;85321:3;85314:4;:10;:::i;:::-;85300:25;;:12;:25;:::i;:::-;85288:37;;85242:95;85347:9;85592:3;85410:15;85405:4;:20;85440:15;85471:8;;85494:5;85515:10;85550:11;85540:22;85374:203;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;85364:224;;;;;;85359:230;;:236;;;;:::i;:::-;85347:248;-1:-1:-1;85613:6:0;85347:248;85618:1;85613:6;:::i;:::-;85606:13;85105:522;-1:-1:-1;;;;;;85105:522:0:o;65810:91::-;65887:6;65869:14;;:24;;;;;;;:::i;:::-;;;;-1:-1:-1;;;65810:91:0:o;73824:196::-;73967:45;73994:4;74000:2;74004:7;73967:26;:45::i;42155:321::-;42285:18;42291:2;42295:7;42285:5;:18::i;:::-;42336:54;42367:1;42371:2;42375:7;42384:5;42336:22;:54::i;:::-;42314:154;;;;-1:-1:-1;;;42314:154:0;;;;;;;:::i;48687:206::-;48756:20;48768:7;48756:11;:20::i;:::-;48799:19;;;;:10;:19;;;;;48793:33;;;;;:::i;:::-;:38;;-1:-1:-1;48789:97:0;;48855:19;;;;:10;:19;;;;;48848:26;;;:::i;61803:716::-;62227:23;62253:69;62281:4;62253:69;;;;;;;;;;;;;;;;;62261:5;-1:-1:-1;;;;;62253:27:0;;;:69;;;;;:::i;:::-;62337:17;;62227:95;;-1:-1:-1;62337:21:0;62333:179;;62434:10;62423:30;;;;;;;;;;;;:::i;:::-;62415:85;;;;-1:-1:-1;;;62415:85:0;;27327:2:1;62415:85:0;;;27309:21:1;27366:2;27346:18;;;27339:30;27405:34;27385:18;;;27378:62;-1:-1:-1;;;27456:18:1;;;27449:40;27506:19;;62415:85:0;27125:406:1;45555:799:0;45710:4;-1:-1:-1;;;;;45731:13:0;;16200:20;16248:8;45727:620;;45767:72;;-1:-1:-1;;;45767:72:0;;-1:-1:-1;;;;;45767:36:0;;;;;:72;;12812:10;;45818:4;;45824:7;;45833:5;;45767:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;45767:72:0;;;;;;;;-1:-1:-1;;45767:72:0;;;;;;;;;;;;:::i;:::-;;;45763:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46009:13:0;;46005:272;;46052:60;;-1:-1:-1;;;46052:60:0;;;;;;;:::i;46005:272::-;46227:6;46221:13;46212:6;46208:2;46204:15;46197:38;45763:529;-1:-1:-1;;;;;;45890:51:0;-1:-1:-1;;;45890:51:0;;-1:-1:-1;45883:58:0;;45727:620;-1:-1:-1;46331:4:0;45555:799;;;;;;:::o;76808:108::-;76868:13;76901:7;76894:14;;;;;:::i;36225:334::-;36298:13;36332:16;36340:7;36332;:16::i;:::-;36324:76;;;;-1:-1:-1;;;36324:76:0;;24270:2:1;36324:76:0;;;24252:21:1;24309:2;24289:18;;;24282:30;24348:34;24328:18;;;24321:62;-1:-1:-1;;;24399:18:1;;;24392:45;24454:19;;36324:76:0;24068:411:1;36324:76:0;36413:21;36437:10;:8;:10::i;:::-;36413:34;;36489:1;36471:7;36465:21;:25;:86;;;;;;;;;;;;;;;;;36517:7;36526:18;:7;:16;:18::i;:::-;36500:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;36458:93;36225:334;-1:-1:-1;;;36225:334:0:o;34936:305::-;35038:4;-1:-1:-1;;;;;;35075:40:0;;-1:-1:-1;;;35075:40:0;;:105;;-1:-1:-1;;;;;;;35132:48:0;;-1:-1:-1;;;35132:48:0;35075:105;:158;;;-1:-1:-1;;;;;;;;;;25716:40:0;;;35197:36;25607:157;51423:589;-1:-1:-1;;;;;51629:18:0;;51625:187;;51664:40;51696:7;52839:10;:17;;52812:24;;;;:15;:24;;;;;:44;;;52867:24;;;;;;;;;;;;52735:164;51664:40;51625:187;;;51734:2;-1:-1:-1;;;;;51726:10:0;:4;-1:-1:-1;;;;;51726:10:0;;51722:90;;51753:47;51786:4;51792:7;51753:32;:47::i;:::-;-1:-1:-1;;;;;51826:16:0;;51822:183;;51859:45;51896:7;51859:36;:45::i;51822:183::-;51932:4;-1:-1:-1;;;;;51926:10:0;:2;-1:-1:-1;;;;;51926:10:0;;51922:83;;51953:40;51981:2;51985:7;51953:27;:40::i;42812:382::-;-1:-1:-1;;;;;42892:16:0;;42884:61;;;;-1:-1:-1;;;42884:61:0;;21537:2:1;42884:61:0;;;21519:21:1;;;21556:18;;;21549:30;21615:34;21595:18;;;21588:62;21667:18;;42884:61:0;21335:356:1;42884:61:0;42965:16;42973:7;42965;:16::i;:::-;42964:17;42956:58;;;;-1:-1:-1;;;42956:58:0;;14859:2:1;42956:58:0;;;14841:21:1;14898:2;14878:18;;;14871:30;14937;14917:18;;;14910:58;14985:18;;42956:58:0;14657:352:1;42956:58:0;43027:45;43056:1;43060:2;43064:7;43027:20;:45::i;:::-;-1:-1:-1;;;;;43085:13:0;;;;;;:9;:13;;;;;:18;;43102:1;;43085:13;:18;;43102:1;;43085:18;:::i;:::-;;;;-1:-1:-1;;43114:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;43114:21:0;-1:-1:-1;;;;;43114:21:0;;;;;;;;43153:33;;43114:16;;;43153:33;;43114:16;;43153:33;42812:382;;:::o;43423:360::-;43483:13;43499:23;43514:7;43499:14;:23::i;:::-;43483:39;;43535:48;43556:5;43571:1;43575:7;43535:20;:48::i;:::-;43624:29;43641:1;43645:7;43624:8;:29::i;:::-;-1:-1:-1;;;;;43666:16:0;;;;;;:9;:16;;;;;:21;;43686:1;;43666:16;:21;;43686:1;;43666:21;:::i;:::-;;;;-1:-1:-1;;43705:16:0;;;;:7;:16;;;;;;43698:23;;-1:-1:-1;;;;;;43698:23:0;;;43739:36;43713:7;;43705:16;-1:-1:-1;;;;;43739:36:0;;;;;43705:16;;43739:36;43472:311;43423:360;:::o;18683:229::-;18820:12;18852:52;18874:6;18882:4;18888:1;18891:12;18852:21;:52::i;10404:723::-;10460:13;10681:10;10677:53;;-1:-1:-1;;10708:10:0;;;;;;;;;;;;-1:-1:-1;;;10708:10:0;;;;;10404:723::o;10677:53::-;10755:5;10740:12;10796:78;10803:9;;10796:78;;10829:8;;;;:::i;:::-;;-1:-1:-1;10852:10:0;;-1:-1:-1;10860:2:0;10852:10;;:::i;:::-;;;10796:78;;;10884:19;10916:6;-1:-1:-1;;;;;10906:17:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10906:17:0;;10884:39;;10934:154;10941:10;;10934:154;;10968:11;10978:1;10968:11;;:::i;:::-;;-1:-1:-1;11037:10:0;11045:2;11037:5;:10;:::i;:::-;11024:24;;:2;:24;:::i;:::-;11011:39;;10994:6;11001;10994:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;10994:56:0;;;;;;;;-1:-1:-1;11065:11:0;11074:2;11065:11;;:::i;:::-;;;10934:154;;53526:988;53792:22;53842:1;53817:22;53834:4;53817:16;:22::i;:::-;:26;;;;:::i;:::-;53854:18;53875:26;;;:17;:26;;;;;;53792:51;;-1:-1:-1;54008:28:0;;;54004:328;;-1:-1:-1;;;;;54075:18:0;;54053:19;54075:18;;;:12;:18;;;;;;;;:34;;;;;;;;;54126:30;;;;;;:44;;;54243:30;;:17;:30;;;;;:43;;;54004:328;-1:-1:-1;54428:26:0;;;;:17;:26;;;;;;;;54421:33;;;-1:-1:-1;;;;;54472:18:0;;;;;:12;:18;;;;;:34;;;;;;;54465:41;53526:988::o;54809:1079::-;55087:10;:17;55062:22;;55087:21;;55107:1;;55087:21;:::i;:::-;55119:18;55140:24;;;:15;:24;;;;;;55513:10;:26;;55062:46;;-1:-1:-1;55140:24:0;;55062:46;;55513:26;;;;;;:::i;:::-;;;;;;;;;55491:48;;55577:11;55552:10;55563;55552:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;55657:28;;;:15;:28;;;;;;;:41;;;55829:24;;;;;55822:31;55864:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;54880:1008;;;54809:1079;:::o;52313:221::-;52398:14;52415:20;52432:2;52415:16;:20::i;:::-;-1:-1:-1;;;;;52446:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;52491:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;52313:221:0:o;19803:510::-;19973:12;20031:5;20006:21;:30;;19998:81;;;;-1:-1:-1;;;19998:81:0;;17945:2:1;19998:81:0;;;17927:21:1;17984:2;17964:18;;;17957:30;18023:34;18003:18;;;17996:62;-1:-1:-1;;;18074:18:1;;;18067:36;18120:19;;19998:81:0;17743:402:1;19998:81:0;16200:20;;20090:60;;;;-1:-1:-1;;;20090:60:0;;25863:2:1;20090:60:0;;;25845:21:1;25902:2;25882:18;;;25875:30;25941:31;25921:18;;;25914:59;25990:18;;20090:60:0;25661:353:1;20090:60:0;20164:12;20178:23;20205:6;-1:-1:-1;;;;;20205:11:0;20224:5;20231:4;20205:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20163:73;;;;20254:51;20271:7;20280:10;20292:12;20254:16;:51::i;:::-;20247:58;19803:510;-1:-1:-1;;;;;;;19803:510:0:o;22489:712::-;22639:12;22668:7;22664:530;;;-1:-1:-1;22699:10:0;22692:17;;22664:530;22813:17;;:21;22809:374;;23011:10;23005:17;23072:15;23059:10;23055:2;23051:19;23044:44;22809:374;23154:12;23147:20;;-1:-1:-1;;;23147:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:468:1;78:5;-1:-1:-1;;;;;104:6:1;101:30;98:56;;;134:18;;:::i;:::-;183:2;177:9;195:69;252:2;231:15;;-1:-1:-1;;227:29:1;258:4;223:40;177:9;195:69;:::i;:::-;282:6;273:15;;312:6;304;297:22;352:3;343:6;338:3;334:16;331:25;328:45;;;369:1;366;359:12;328:45;419:6;414:3;407:4;399:6;395:17;382:44;474:1;467:4;458:6;450;446:19;442:30;435:41;;14:468;;;;;:::o;487:221::-;530:5;583:3;576:4;568:6;564:17;560:27;550:55;;601:1;598;591:12;550:55;623:79;698:3;689:6;676:20;669:4;661:6;657:17;623:79;:::i;713:247::-;772:6;825:2;813:9;804:7;800:23;796:32;793:52;;;841:1;838;831:12;793:52;880:9;867:23;899:31;924:5;899:31;:::i;1225:388::-;1293:6;1301;1354:2;1342:9;1333:7;1329:23;1325:32;1322:52;;;1370:1;1367;1360:12;1322:52;1409:9;1396:23;1428:31;1453:5;1428:31;:::i;:::-;1478:5;-1:-1:-1;1535:2:1;1520:18;;1507:32;1548:33;1507:32;1548:33;:::i;:::-;1600:7;1590:17;;;1225:388;;;;;:::o;1618:456::-;1695:6;1703;1711;1764:2;1752:9;1743:7;1739:23;1735:32;1732:52;;;1780:1;1777;1770:12;1732:52;1819:9;1806:23;1838:31;1863:5;1838:31;:::i;:::-;1888:5;-1:-1:-1;1945:2:1;1930:18;;1917:32;1958:33;1917:32;1958:33;:::i;:::-;1618:456;;2010:7;;-1:-1:-1;;;2064:2:1;2049:18;;;;2036:32;;1618:456::o;2079:794::-;2174:6;2182;2190;2198;2251:3;2239:9;2230:7;2226:23;2222:33;2219:53;;;2268:1;2265;2258:12;2219:53;2307:9;2294:23;2326:31;2351:5;2326:31;:::i;:::-;2376:5;-1:-1:-1;2433:2:1;2418:18;;2405:32;2446:33;2405:32;2446:33;:::i;:::-;2498:7;-1:-1:-1;2552:2:1;2537:18;;2524:32;;-1:-1:-1;2607:2:1;2592:18;;2579:32;-1:-1:-1;;;;;2623:30:1;;2620:50;;;2666:1;2663;2656:12;2620:50;2689:22;;2742:4;2734:13;;2730:27;-1:-1:-1;2720:55:1;;2771:1;2768;2761:12;2720:55;2794:73;2859:7;2854:2;2841:16;2836:2;2832;2828:11;2794:73;:::i;:::-;2784:83;;;2079:794;;;;;;;:::o;2878:382::-;2943:6;2951;3004:2;2992:9;2983:7;2979:23;2975:32;2972:52;;;3020:1;3017;3010:12;2972:52;3059:9;3046:23;3078:31;3103:5;3078:31;:::i;:::-;3128:5;-1:-1:-1;3185:2:1;3170:18;;3157:32;3198:30;3157:32;3198:30;:::i;3265:315::-;3333:6;3341;3394:2;3382:9;3373:7;3369:23;3365:32;3362:52;;;3410:1;3407;3400:12;3362:52;3449:9;3436:23;3468:31;3493:5;3468:31;:::i;:::-;3518:5;3570:2;3555:18;;;;3542:32;;-1:-1:-1;;;3265:315:1:o;3585:615::-;3671:6;3679;3732:2;3720:9;3711:7;3707:23;3703:32;3700:52;;;3748:1;3745;3738:12;3700:52;3788:9;3775:23;-1:-1:-1;;;;;3858:2:1;3850:6;3847:14;3844:34;;;3874:1;3871;3864:12;3844:34;3912:6;3901:9;3897:22;3887:32;;3957:7;3950:4;3946:2;3942:13;3938:27;3928:55;;3979:1;3976;3969:12;3928:55;4019:2;4006:16;4045:2;4037:6;4034:14;4031:34;;;4061:1;4058;4051:12;4031:34;4114:7;4109:2;4099:6;4096:1;4092:14;4088:2;4084:23;4080:32;4077:45;4074:65;;;4135:1;4132;4125:12;4074:65;4166:2;4158:11;;;;;4188:6;;-1:-1:-1;3585:615:1;;-1:-1:-1;;;;3585:615:1:o;4205:241::-;4261:6;4314:2;4302:9;4293:7;4289:23;4285:32;4282:52;;;4330:1;4327;4320:12;4282:52;4369:9;4356:23;4388:28;4410:5;4388:28;:::i;4451:245::-;4518:6;4571:2;4559:9;4550:7;4546:23;4542:32;4539:52;;;4587:1;4584;4577:12;4539:52;4619:9;4613:16;4638:28;4660:5;4638:28;:::i;4701:245::-;4759:6;4812:2;4800:9;4791:7;4787:23;4783:32;4780:52;;;4828:1;4825;4818:12;4780:52;4867:9;4854:23;4886:30;4910:5;4886:30;:::i;4951:249::-;5020:6;5073:2;5061:9;5052:7;5048:23;5044:32;5041:52;;;5089:1;5086;5079:12;5041:52;5121:9;5115:16;5140:30;5164:5;5140:30;:::i;5880:338::-;5962:6;5970;6023:2;6011:9;6002:7;5998:23;5994:32;5991:52;;;6039:1;6036;6029:12;5991:52;6078:9;6065:23;6117:1;6110:5;6107:12;6097:40;;6133:1;6130;6123:12;6223:322;6292:6;6345:2;6333:9;6324:7;6320:23;6316:32;6313:52;;;6361:1;6358;6351:12;6313:52;6401:9;6388:23;-1:-1:-1;;;;;6426:6:1;6423:30;6420:50;;;6466:1;6463;6456:12;6420:50;6489;6531:7;6522:6;6511:9;6507:22;6489:50;:::i;6550:180::-;6609:6;6662:2;6650:9;6641:7;6637:23;6633:32;6630:52;;;6678:1;6675;6668:12;6630:52;-1:-1:-1;6701:23:1;;6550:180;-1:-1:-1;6550:180:1:o;6735:184::-;6805:6;6858:2;6846:9;6837:7;6833:23;6829:32;6826:52;;;6874:1;6871;6864:12;6826:52;-1:-1:-1;6897:16:1;;6735:184;-1:-1:-1;6735:184:1:o;6924:390::-;7002:6;7010;7063:2;7051:9;7042:7;7038:23;7034:32;7031:52;;;7079:1;7076;7069:12;7031:52;7115:9;7102:23;7092:33;;7176:2;7165:9;7161:18;7148:32;-1:-1:-1;;;;;7195:6:1;7192:30;7189:50;;;7235:1;7232;7225:12;7189:50;7258;7300:7;7291:6;7280:9;7276:22;7258:50;:::i;7319:248::-;7387:6;7395;7448:2;7436:9;7427:7;7423:23;7419:32;7416:52;;;7464:1;7461;7454:12;7416:52;-1:-1:-1;;7487:23:1;;;7557:2;7542:18;;;7529:32;;-1:-1:-1;7319:248:1:o;7572:257::-;7613:3;7651:5;7645:12;7678:6;7673:3;7666:19;7694:63;7750:6;7743:4;7738:3;7734:14;7727:4;7720:5;7716:16;7694:63;:::i;:::-;7811:2;7790:15;-1:-1:-1;;7786:29:1;7777:39;;;;7818:4;7773:50;;7572:257;-1:-1:-1;;7572:257:1:o;8318:274::-;8447:3;8485:6;8479:13;8501:53;8547:6;8542:3;8535:4;8527:6;8523:17;8501:53;:::i;:::-;8570:16;;;;;8318:274;-1:-1:-1;;8318:274:1:o;8597:470::-;8776:3;8814:6;8808:13;8830:53;8876:6;8871:3;8864:4;8856:6;8852:17;8830:53;:::i;:::-;8946:13;;8905:16;;;;8968:57;8946:13;8905:16;9002:4;8990:17;;8968:57;:::i;:::-;9041:20;;8597:470;-1:-1:-1;;;;8597:470:1:o;9072:438::-;-1:-1:-1;;;9327:3:1;9320:36;9302:3;9385:6;9379:13;9401:62;9456:6;9451:2;9446:3;9442:12;9435:4;9427:6;9423:17;9401:62;:::i;:::-;9483:16;;;;9501:2;9479:25;;9072:438;-1:-1:-1;;9072:438:1:o;9725:672::-;10034:6;10029:3;10022:19;10071:6;10066:2;10061:3;10057:12;10050:28;10122:6;10114;10109:2;10104:3;10100:12;10087:42;10191:2;10148:16;;10183:11;;;10225:18;;;;10280:2;10276:15;;;-1:-1:-1;;;;;;10272:53:1;10259:11;;;10252:74;10350:3;10342:12;;10335:28;10387:3;10379:12;;9725:672;-1:-1:-1;;;9725:672:1:o;11121:488::-;-1:-1:-1;;;;;11390:15:1;;;11372:34;;11442:15;;11437:2;11422:18;;11415:43;11489:2;11474:18;;11467:34;;;11537:3;11532:2;11517:18;;11510:31;;;11315:4;;11558:45;;11583:19;;11575:6;11558:45;:::i;12085:413::-;12259:2;12244:18;;12292:1;12281:13;;12271:144;;12337:10;12332:3;12328:20;12325:1;12318:31;12372:4;12369:1;12362:15;12400:4;12397:1;12390:15;12271:144;12424:25;;;12480:2;12465:18;12458:34;12085:413;:::o;12503:219::-;12652:2;12641:9;12634:21;12615:4;12672:44;12712:2;12701:9;12697:18;12689:6;12672:44;:::i;13478:414::-;13680:2;13662:21;;;13719:2;13699:18;;;13692:30;13758:34;13753:2;13738:18;;13731:62;-1:-1:-1;;;13824:2:1;13809:18;;13802:48;13882:3;13867:19;;13478:414::o;15432:402::-;15634:2;15616:21;;;15673:2;15653:18;;;15646:30;15712:34;15707:2;15692:18;;15685:62;-1:-1:-1;;;15778:2:1;15763:18;;15756:36;15824:3;15809:19;;15432:402::o;18563:407::-;18765:2;18747:21;;;18804:2;18784:18;;;18777:30;18843:34;18838:2;18823:18;;18816:62;-1:-1:-1;;;18909:2:1;18894:18;;18887:41;18960:3;18945:19;;18563:407::o;22527:356::-;22729:2;22711:21;;;22748:18;;;22741:30;22807:34;22802:2;22787:18;;22780:62;22874:2;22859:18;;22527:356::o;25243:413::-;25445:2;25427:21;;;25484:2;25464:18;;;25457:30;25523:34;25518:2;25503:18;;25496:62;-1:-1:-1;;;25589:2:1;25574:18;;25567:47;25646:3;25631:19;;25243:413::o;27884:342::-;28086:2;28068:21;;;28125:2;28105:18;;;28098:30;-1:-1:-1;;;28159:2:1;28144:18;;28137:48;28217:2;28202:18;;27884:342::o;28583:348::-;28785:2;28767:21;;;28824:2;28804:18;;;28797:30;28863:26;28858:2;28843:18;;28836:54;28922:2;28907:18;;28583:348::o;28936:332::-;29138:2;29120:21;;;29177:1;29157:18;;;29150:29;-1:-1:-1;;;29210:2:1;29195:18;;29188:39;29259:2;29244:18;;28936:332::o;30058:128::-;30098:3;30129:1;30125:6;30122:1;30119:13;30116:39;;;30135:18;;:::i;:::-;-1:-1:-1;30171:9:1;;30058:128::o;30191:120::-;30231:1;30257;30247:35;;30262:18;;:::i;:::-;-1:-1:-1;30296:9:1;;30191:120::o;30316:168::-;30356:7;30422:1;30418;30414:6;30410:14;30407:1;30404:21;30399:1;30392:9;30385:17;30381:45;30378:71;;;30429:18;;:::i;:::-;-1:-1:-1;30469:9:1;;30316:168::o;30489:125::-;30529:4;30557:1;30554;30551:8;30548:34;;;30562:18;;:::i;:::-;-1:-1:-1;30599:9:1;;30489:125::o;30619:258::-;30691:1;30701:113;30715:6;30712:1;30709:13;30701:113;;;30791:11;;;30785:18;30772:11;;;30765:39;30737:2;30730:10;30701:113;;;30832:6;30829:1;30826:13;30823:48;;;-1:-1:-1;;30867:1:1;30849:16;;30842:27;30619:258::o;30882:193::-;30920:3;-1:-1:-1;;;;;30957:5:1;30953:30;31002:7;30992:41;;31013:18;;:::i;:::-;-1:-1:-1;;31049:20:1;;30882:193;-1:-1:-1;;30882:193:1:o;31080:380::-;31159:1;31155:12;;;;31202;;;31223:61;;31277:4;31269:6;31265:17;31255:27;;31223:61;31330:2;31322:6;31319:14;31299:18;31296:38;31293:161;;;31376:10;31371:3;31367:20;31364:1;31357:31;31411:4;31408:1;31401:15;31439:4;31436:1;31429:15;31293:161;;31080:380;;;:::o;31465:249::-;31575:2;31556:13;;-1:-1:-1;;31552:27:1;31540:40;;-1:-1:-1;;;;;31595:34:1;;31631:22;;;31592:62;31589:88;;;31657:18;;:::i;:::-;31693:2;31686:22;-1:-1:-1;;31465:249:1:o;31719:135::-;31758:3;-1:-1:-1;;31779:17:1;;31776:43;;;31799:18;;:::i;:::-;-1:-1:-1;31846:1:1;31835:13;;31719:135::o;31859:112::-;31891:1;31917;31907:35;;31922:18;;:::i;:::-;-1:-1:-1;31956:9:1;;31859:112::o;31976:127::-;32037:10;32032:3;32028:20;32025:1;32018:31;32068:4;32065:1;32058:15;32092:4;32089:1;32082:15;32108:127;32169:10;32164:3;32160:20;32157:1;32150:31;32200:4;32197:1;32190:15;32224:4;32221:1;32214:15;32240:127;32301:10;32296:3;32292:20;32289:1;32282:31;32332:4;32329:1;32322:15;32356:4;32353:1;32346:15;32372:127;32433:10;32428:3;32424:20;32421:1;32414:31;32464:4;32461:1;32454:15;32488:4;32485:1;32478:15;32504:127;32565:10;32560:3;32556:20;32553:1;32546:31;32596:4;32593:1;32586:15;32620:4;32617:1;32610:15;32636:127;32697:10;32692:3;32688:20;32685:1;32678:31;32728:4;32725:1;32718:15;32752:4;32749:1;32742:15;32768:179;32803:3;32845:1;32827:16;32824:23;32821:120;;;32891:1;32888;32885;32870:23;-1:-1:-1;32928:1:1;32922:8;32917:3;32913:18;32821:120;32768:179;:::o;32952:671::-;32991:3;33033:4;33015:16;33012:26;33009:39;;;32952:671;:::o;33009:39::-;33075:2;33069:9;-1:-1:-1;;33140:16:1;33136:25;;33133:1;33069:9;33112:50;33191:4;33185:11;33215:16;-1:-1:-1;;;;;33321:2:1;33314:4;33306:6;33302:17;33299:25;33294:2;33286:6;33283:14;33280:45;33277:58;;;33328:5;;;;;32952:671;:::o;33277:58::-;33365:6;33359:4;33355:17;33344:28;;33401:3;33395:10;33428:2;33420:6;33417:14;33414:27;;;33434:5;;;;;;32952:671;:::o;33414:27::-;33518:2;33499:16;33493:4;33489:27;33485:36;33478:4;33469:6;33464:3;33460:16;33456:27;33453:69;33450:82;;;33525:5;;;;;;32952:671;:::o;33450:82::-;33541:57;33592:4;33583:6;33575;33571:19;33567:30;33561:4;33541:57;:::i;:::-;-1:-1:-1;33614:3:1;;32952:671;-1:-1:-1;;;;;32952:671:1:o;33628:131::-;-1:-1:-1;;;;;33703:31:1;;33693:42;;33683:70;;33749:1;33746;33739:12;33764:118;33850:5;33843:13;33836:21;33829:5;33826:32;33816:60;;33872:1;33869;33862:12;33887:131;-1:-1:-1;;;;;;33961:32:1;;33951:43;;33941:71;;34008:1;34005;33998:12

Swarm Source

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