ETH Price: $2,672.72 (+1.34%)

Token

BestGirls (BestGirls)
 

Overview

Max Total Supply

881 BestGirls

Holders

309

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
monayo.eth
Balance
2 BestGirls
0xedd6347f4116d333b75bb193de8602e7ec050f05
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
SBII721A

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 1 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-04-21
*/

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

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

// File: ISBShipable.sol


// author: yoyoismee.eth -- it's opensource but also feel free to send me coffee/beer.
//  ╔═╗┌─┐┌─┐┌─┐┌┬┐┌┐ ┌─┐┌─┐┌┬┐┌─┐┌┬┐┬ ┬┌┬┐┬┌─┐
//  ╚═╗├─┘├┤ ├┤  ││├┴┐│ │├─┤ │ └─┐ │ │ │ ││││ │
//  ╚═╝┴  └─┘└─┘─┴┘└─┘└─┘┴ ┴ ┴o└─┘ ┴ └─┘─┴┘┴└─┘

pragma solidity 0.8.13;

interface ISBShipable {
    function initialize(
        bytes calldata initArg,
        uint128 bip,
        address feeReceiver
    ) external;
}

// File: ISBMintable.sol


// author: yoyoismee.eth -- it's opensource but also feel free to send me coffee/beer.
//  ╔═╗┌─┐┌─┐┌─┐┌┬┐┌┐ ┌─┐┌─┐┌┬┐┌─┐┌┬┐┬ ┬┌┬┐┬┌─┐
//  ╚═╗├─┘├┤ ├┤  ││├┴┐│ │├─┤ │ └─┐ │ │ │ ││││ │
//  ╚═╝┴  └─┘└─┘─┴┘└─┘└─┘┴ ┴ ┴o└─┘ ┴ └─┘─┴┘┴└─┘

pragma solidity 0.8.13;

interface ISBMintable {
    function mintNext(address reciever, uint256 amount) external;

    function mintTarget(address reciever, uint256 target) external;
}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)

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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from,
        address to,
        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);
}

// File: @openzeppelin/contracts/utils/cryptography/MerkleProof.sol


// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Trees proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];
            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = _efficientHash(computedHash, proofElement);
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = _efficientHash(proofElement, computedHash);
            }
        }
        return computedHash;
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

// File: @openzeppelin/contracts/interfaces/IERC1271.sol


// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 *
 * _Available since v4.1._
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with _data
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

// File: @openzeppelin/contracts/utils/Address.sol


// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @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
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

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

// File: paymentUtil.sol


// author: yoyoismee.eth -- it's opensource but also feel free to send me coffee/beer.
//  ╔═╗┌─┐┌─┐┌─┐┌┬┐┌┐ ┌─┐┌─┐┌┬┐┌─┐┌┬┐┬ ┬┌┬┐┬┌─┐
//  ╚═╗├─┘├┤ ├┤  ││├┴┐│ │├─┤ │ └─┐ │ │ │ ││││ │
//  ╚═╝┴  └─┘└─┘─┴┘└─┘└─┘┴ ┴ ┴o└─┘ ┴ └─┘─┴┘┴└─┘

pragma solidity 0.8.13;



library paymentUtil {
    using SafeERC20 for IERC20;

    function processPayment(address token, uint256 amount) public {
        if (token == address(0)) {
            require(msg.value >= amount, "invalid payment");
        } else {
            IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
        }
    }
}

// File: @openzeppelin/contracts/utils/Strings.sol


// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

// File: @openzeppelin/contracts/utils/cryptography/ECDSA.sol


// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

        return (signer, RecoverError.NoError);
    }

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

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

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

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

// File: @openzeppelin/contracts/utils/cryptography/SignatureChecker.sol


// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/SignatureChecker.sol)

pragma solidity ^0.8.0;




/**
 * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
 * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
 * Argent and Gnosis Safe.
 *
 * _Available since v4.1._
 */
library SignatureChecker {
    /**
     * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
     * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
     *
     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
     * change through time. It could return true at block N and false at block N+1 (or the opposite).
     */
    function isValidSignatureNow(
        address signer,
        bytes32 hash,
        bytes memory signature
    ) internal view returns (bool) {
        (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
        if (error == ECDSA.RecoverError.NoError && recovered == signer) {
            return true;
        }

        (bool success, bytes memory result) = signer.staticcall(
            abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
        );
        return (success && result.length == 32 && abi.decode(result, (bytes4)) == IERC1271.isValidSignature.selector);
    }
}

// File: @openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSetUpgradeable {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastvalue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastvalue;
                // Update the index for the moved value
                set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        return _values(set._inner);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly {
            result := store
        }

        return result;
    }
}

// File: @openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

// File: @openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;


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

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

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

// File: @openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

// File: @openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControlUpgradeable {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

// File: @openzeppelin/contracts-upgradeable/access/IAccessControlEnumerableUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)

pragma solidity ^0.8.0;


/**
 * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
 */
interface IAccessControlEnumerableUpgradeable is IAccessControlUpgradeable {
    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) external view returns (address);

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) external view returns (uint256);
}

// File: @openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol


// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @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
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

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

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

// File: @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol


// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.0;


/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
 * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() initializer {}
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        // If the contract is initializing we ignore whether _initialized is set in order to support multiple
        // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
        // contract may have been reentered.
        require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} modifier, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

// File: @openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;



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

    function __ERC165_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165Upgradeable).interfaceId;
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

// File: @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;


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

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

// File: ERC721ASBUpgradable.sol


// author: yoyoismee.eth -- it's opensource but also feel free to send me coffee/beer.
//  ╔═╗┌─┐┌─┐┌─┐┌┬┐┌┐ ┌─┐┌─┐┌┬┐┌─┐┌┬┐┬ ┬┌┬┐┬┌─┐
//  ╚═╗├─┘├┤ ├┤  ││├┴┐│ │├─┤ │ └─┐ │ │ │ ││││ │
//  ╚═╝┴  └─┘└─┘─┴┘└─┘└─┘┴ ┴ ┴o└─┘ ┴ └─┘─┴┘┴└─┘


// ERC721A Creator: Chiru Labs
// GJ mate. interesting design :)

pragma solidity 0.8.13;









error ApprovalCallerNotOwnerNorApproved();
error ApprovalQueryForNonexistentToken();
error ApproveToCaller();
error ApprovalToCurrentOwner();
error BalanceQueryForZeroAddress();
error MintToZeroAddress();
error MintZeroQuantity();
error OwnerQueryForNonexistentToken();
error TransferCallerNotOwnerNorApproved();
error TransferFromIncorrectOwner();
error TransferToNonERC721ReceiverImplementer();
error TransferToZeroAddress();
error URIQueryForNonexistentToken();
error AllOwnershipsHaveBeenSet();
error QuantityMustBeNonZero();
error NoTokensMintedYet();
error InvalidQueryRange();

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension. Built to optimize for lower gas during batch mints.
 *
 * Assumes serials are sequentially minted starting at _startTokenId() (defaults to 0, e.g. 0, 1, 2, 3..).
 *
 * Assumes that an owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
 *
 * Assumes that the maximum token id cannot exceed 2**256 - 1 (max value of uint256).
 *
 * Speedboat team modified version of ERC721A - upgradable
 */
contract ERC721ASBUpgradable is
    Initializable,
    ContextUpgradeable,
    ERC165Upgradeable,
    IERC721Upgradeable,
    IERC721MetadataUpgradeable
{
    using Address for address;
    using Strings for uint256;

    // Compiler will pack this into a single 256bit word.
    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Keeps track of the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
    }

    // Compiler will pack this into a single 256bit word.
    struct AddressData {
        // Realistically, 2**64-1 is more than enough.
        uint64 balance;
        // Keeps track of mint count with minimal overhead for tokenomics.
        uint64 numberMinted;
        // Keeps track of burn count with minimal overhead for tokenomics.
        uint64 numberBurned;
        // For miscellaneous variable(s) pertaining to the address
        // (e.g. number of whitelist mint slots used).
        // If there are multiple variables, please pack them into a uint64.
        uint64 aux;
    }

    // The tokenId of the next token to be minted.
    uint256 internal _currentIndex;

    // The number of tokens burned.
    uint256 internal _burnCounter;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned. See _ownershipOf implementation for details.
    mapping(uint256 => TokenOwnership) internal _ownerships;

    // Mapping owner address to address data
    mapping(address => AddressData) private _addressData;

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

    uint256 public nextOwnerToExplicitlySet;

    /**
     * @dev Explicitly set `owners` to eliminate loops in future calls of ownerOf().
     * SB: change to public. anyone are free to pay the gas lol :P
     */
    function setOwnersExplicit(uint256 quantity) public {
        if (quantity == 0) revert QuantityMustBeNonZero();
        if (_currentIndex == _startTokenId()) revert NoTokensMintedYet();
        uint256 _nextOwnerToExplicitlySet = nextOwnerToExplicitlySet;
        if (_nextOwnerToExplicitlySet == 0) {
            _nextOwnerToExplicitlySet = _startTokenId();
        }
        if (_nextOwnerToExplicitlySet >= _currentIndex)
            revert AllOwnershipsHaveBeenSet();

        // Index underflow is impossible.
        // Counter or index overflow is incredibly unrealistic.
        unchecked {
            uint256 endIndex = _nextOwnerToExplicitlySet + quantity - 1;

            // Set the end index to be the last token index
            if (endIndex + 1 > _currentIndex) {
                endIndex = _currentIndex - 1;
            }

            for (uint256 i = _nextOwnerToExplicitlySet; i <= endIndex; i++) {
                if (
                    _ownerships[i].addr == address(0) && !_ownerships[i].burned
                ) {
                    TokenOwnership memory ownership = _ownershipOf(i);
                    _ownerships[i].addr = ownership.addr;
                    _ownerships[i].startTimestamp = ownership.startTimestamp;
                }
            }

            nextOwnerToExplicitlySet = endIndex + 1;
        }
    }

    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *   - `addr` = `address(0)`
     *   - `startTimestamp` = `0`
     *   - `burned` = `false`
     *
     * If the `tokenId` is burned:
     *   - `addr` = `<Address of owner before token was burned>`
     *   - `startTimestamp` = `<Timestamp when token was burned>`
     *   - `burned = `true`
     *
     * Otherwise:
     *   - `addr` = `<Address of owner>`
     *   - `startTimestamp` = `<Timestamp of start of ownership>`
     *   - `burned = `false`
     */
    function explicitOwnershipOf(uint256 tokenId)
        public
        view
        returns (TokenOwnership memory)
    {
        TokenOwnership memory ownership;
        if (tokenId < _startTokenId() || tokenId >= _currentIndex) {
            return ownership;
        }
        ownership = _ownerships[tokenId];
        if (ownership.burned) {
            return ownership;
        }
        return _ownershipOf(tokenId);
    }

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] memory tokenIds)
        external
        view
        returns (TokenOwnership[] memory)
    {
        unchecked {
            uint256 tokenIdsLength = tokenIds.length;
            TokenOwnership[] memory ownerships = new TokenOwnership[](
                tokenIdsLength
            );
            for (uint256 i; i != tokenIdsLength; ++i) {
                ownerships[i] = explicitOwnershipOf(tokenIds[i]);
            }
            return ownerships;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start` < `stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view returns (uint256[] memory) {
        unchecked {
            if (start >= stop) revert InvalidQueryRange();
            uint256 tokenIdsIdx;
            uint256 stopLimit = _currentIndex;
            // Set `start = max(start, _startTokenId())`.
            if (start < _startTokenId()) {
                start = _startTokenId();
            }
            // Set `stop = min(stop, _currentIndex)`.
            if (stop > stopLimit) {
                stop = stopLimit;
            }
            uint256 tokenIdsMaxLength = balanceOf(owner);
            // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`,
            // to cater for cases where `balanceOf(owner)` is too big.
            if (start < stop) {
                uint256 rangeLength = stop - start;
                if (rangeLength < tokenIdsMaxLength) {
                    tokenIdsMaxLength = rangeLength;
                }
            } else {
                tokenIdsMaxLength = 0;
            }
            uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength);
            if (tokenIdsMaxLength == 0) {
                return tokenIds;
            }
            // We need to call `explicitOwnershipOf(start)`,
            // because the slot at `start` may not be initialized.
            TokenOwnership memory ownership = explicitOwnershipOf(start);
            address currOwnershipAddr;
            // If the starting slot exists (i.e. not burned), initialize `currOwnershipAddr`.
            // `ownership.address` will not be zero, as `start` is clamped to the valid token ID range.
            if (!ownership.burned) {
                currOwnershipAddr = ownership.addr;
            }
            for (
                uint256 i = start;
                i != stop && tokenIdsIdx != tokenIdsMaxLength;
                ++i
            ) {
                ownership = _ownerships[i];
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            // Downsize the array to fit.
            assembly {
                mstore(tokenIds, tokenIdsIdx)
            }
            return tokenIds;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(totalSupply) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K pfp collections should be fine).
     */
    function tokensOfOwner(address owner)
        public
        view
        returns (uint256[] memory)
    {
        unchecked {
            uint256 tokenIdsIdx;
            address currOwnershipAddr;
            uint256 tokenIdsLength = balanceOf(owner);
            uint256[] memory tokenIds = new uint256[](tokenIdsLength);
            TokenOwnership memory ownership;
            for (
                uint256 i = _startTokenId();
                tokenIdsIdx != tokenIdsLength;
                ++i
            ) {
                ownership = _ownerships[i];
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            return tokenIds;
        }
    }

    function __ERC721A_init(string memory name_, string memory symbol_)
        public
    {
        __Context_init_unchained();
        __ERC165_init_unchained();
        _name = name_;
        _symbol = symbol_;
        _currentIndex = _startTokenId();
    }

    /**
     * To change the starting tokenId, please override this function.
     */
    function _startTokenId() internal view virtual returns (uint256) {
        return 1; // SB: change to start from 1 - modified from original 0. since others SB's code reserve 0 for a random stuff
    }

    /**
     * @dev Burned tokens are calculated here, use _totalMinted() if you want to count just minted tokens.
     */
    function totalSupply() public view returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than _currentIndex - _startTokenId() times
        unchecked {
            return _currentIndex - _burnCounter - _startTokenId();
        }
    }

    /**
     * Returns the total amount of tokens minted in the contract.
     */
    function _totalMinted() internal view returns (uint256) {
        // Counter underflow is impossible as _currentIndex does not decrement,
        // and it is initialized to _startTokenId()
        unchecked {
            return _currentIndex - _startTokenId();
        }
    }

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

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view override returns (uint256) {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return uint256(_addressData[owner].balance);
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return uint256(_addressData[owner].numberMinted);
    }

    /**
     * Returns the number of tokens burned by or on behalf of `owner`.
     */
    function _numberBurned(address owner) internal view returns (uint256) {
        return uint256(_addressData[owner].numberBurned);
    }

    /**
     * Returns the auxillary data for `owner`. (e.g. number of whitelist mint slots used).
     */
    function _getAux(address owner) internal view returns (uint64) {
        return _addressData[owner].aux;
    }

    /**
     * Sets the auxillary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal {
        _addressData[owner].aux = aux;
    }

    /**
     * Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around in the collection over time.
     */
    function _ownershipOf(uint256 tokenId)
        internal
        view
        returns (TokenOwnership memory)
    {
        uint256 curr = tokenId;

        unchecked {
            if (_startTokenId() <= curr && curr < _currentIndex) {
                TokenOwnership memory ownership = _ownerships[curr];
                if (!ownership.burned) {
                    if (ownership.addr != address(0)) {
                        return ownership;
                    }
                    // Invariant:
                    // There will always be an ownership that has an address and is not burned
                    // before an ownership that does not have an address and is not burned.
                    // Hence, curr will not underflow.
                    while (true) {
                        curr--;
                        ownership = _ownerships[curr];
                        if (ownership.addr != address(0)) {
                            return ownership;
                        }
                    }
                }
            }
        }
        revert OwnerQueryForNonexistentToken();
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view override returns (address) {
        return _ownershipOf(tokenId).addr;
    }

    /**
     * @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)
    {
        if (!_exists(tokenId)) revert URIQueryForNonexistentToken();

        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 override {
        address owner = ownerOf(tokenId);
        if (to == owner) revert ApprovalToCurrentOwner();

        if (_msgSender() != owner && !isApprovedForAll(owner, _msgSender())) {
            revert ApprovalCallerNotOwnerNorApproved();
        }

        _approve(to, tokenId, owner);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId)
        public
        view
        override
        returns (address)
    {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId];
    }

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

        _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 {
        _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 {
        _transfer(from, to, tokenId);
        if (
            to.isContract() &&
            !_checkContractOnERC721Received(from, to, tokenId, _data)
        ) {
            revert TransferToNonERC721ReceiverImplementer();
        }
    }

    /**
     * @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`),
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return
            _startTokenId() <= tokenId &&
            tokenId < _currentIndex &&
            !_ownerships[tokenId].burned;
    }

    /**
     * @dev Equivalent to `_safeMint(to, quantity, '')`.
     */
    function _safeMint(address to, uint256 quantity) internal {
        _safeMint(to, quantity, "");
    }

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement
     *   {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) revert MintToZeroAddress();
        if (quantity == 0) revert MintZeroQuantity();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1
        // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1
        unchecked {
            _addressData[to].balance += uint64(quantity);
            _addressData[to].numberMinted += uint64(quantity);

            _ownerships[startTokenId].addr = to;
            _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);

            uint256 updatedIndex = startTokenId;
            uint256 end = updatedIndex + quantity;

            if (to.isContract()) {
                do {
                    emit Transfer(address(0), to, updatedIndex);
                    if (
                        !_checkContractOnERC721Received(
                            address(0),
                            to,
                            updatedIndex++,
                            _data
                        )
                    ) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (updatedIndex != end);
                // Reentrancy protection
                if (_currentIndex != startTokenId) revert();
            } else {
                do {
                    emit Transfer(address(0), to, updatedIndex++);
                } while (updatedIndex != end);
            }
            _currentIndex = updatedIndex;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 quantity) internal {
        uint256 startTokenId = _currentIndex;
        if (to == address(0)) revert MintToZeroAddress();
        if (quantity == 0) revert MintZeroQuantity();

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1
        // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1
        unchecked {
            _addressData[to].balance += uint64(quantity);
            _addressData[to].numberMinted += uint64(quantity);

            _ownerships[startTokenId].addr = to;
            _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);

            uint256 updatedIndex = startTokenId;
            uint256 end = updatedIndex + quantity;

            do {
                emit Transfer(address(0), to, updatedIndex++);
            } while (updatedIndex != end);

            _currentIndex = updatedIndex;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * 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
    ) private {
        TokenOwnership memory prevOwnership = _ownershipOf(tokenId);

        if (prevOwnership.addr != from) revert TransferFromIncorrectOwner();

        bool isApprovedOrOwner = (_msgSender() == from ||
            isApprovedForAll(from, _msgSender()) ||
            getApproved(tokenId) == _msgSender());

        if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

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

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256.
        unchecked {
            _addressData[from].balance -= 1;
            _addressData[to].balance += 1;

            TokenOwnership storage currSlot = _ownerships[tokenId];
            currSlot.addr = to;
            currSlot.startTimestamp = uint64(block.timestamp);

            // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            TokenOwnership storage nextSlot = _ownerships[nextTokenId];
            if (nextSlot.addr == address(0)) {
                // This will suffice for checking _exists(nextTokenId),
                // as a burned slot cannot contain the zero address.
                if (nextTokenId != _currentIndex) {
                    nextSlot.addr = from;
                    nextSlot.startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

        emit Transfer(from, to, tokenId);
        _afterTokenTransfers(from, to, tokenId, 1);
    }

    /**
     * @dev Equivalent to `_burn(tokenId, false)`.
     */
    function _burn(uint256 tokenId) internal virtual {
        _burn(tokenId, false);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId, bool approvalCheck) internal virtual {
        TokenOwnership memory prevOwnership = _ownershipOf(tokenId);

        address from = prevOwnership.addr;

        if (approvalCheck) {
            bool isApprovedOrOwner = (_msgSender() == from ||
                isApprovedForAll(from, _msgSender()) ||
                getApproved(tokenId) == _msgSender());

            if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        }

        _beforeTokenTransfers(from, address(0), tokenId, 1);

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

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256.
        unchecked {
            AddressData storage addressData = _addressData[from];
            addressData.balance -= 1;
            addressData.numberBurned += 1;

            // Keep track of who burned the token, and the timestamp of burning.
            TokenOwnership storage currSlot = _ownerships[tokenId];
            currSlot.addr = from;
            currSlot.startTimestamp = uint64(block.timestamp);
            currSlot.burned = true;

            // If the ownership slot of tokenId+1 is not explicitly set, that means the burn initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            TokenOwnership storage nextSlot = _ownerships[nextTokenId];
            if (nextSlot.addr == address(0)) {
                // This will suffice for checking _exists(nextTokenId),
                // as a burned slot cannot contain the zero address.
                if (nextTokenId != _currentIndex) {
                    nextSlot.addr = from;
                    nextSlot.startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

        emit Transfer(from, address(0), tokenId);
        _afterTokenTransfers(from, address(0), tokenId, 1);

        // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.
        unchecked {
            _burnCounter++;
        }
    }

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

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target 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 _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        try
            IERC721Receiver(to).onERC721Received(
                _msgSender(),
                from,
                tokenId,
                _data
            )
        returns (bytes4 retval) {
            return retval == IERC721Receiver(to).onERC721Received.selector;
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                revert TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token ids are about to be transferred. This includes minting.
     * And also called before burning one token.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * 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, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token ids have been transferred. This includes
     * minting.
     * And also called after one token has been burned.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
     * transferred to `to`.
     * - When `from` is zero, `tokenId` has been minted for `to`.
     * - When `to` is zero, `tokenId` has been burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}
}

// File: @openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol


// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol)

pragma solidity ^0.8.0;






/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {
    function __AccessControl_init() internal onlyInitializing {
    }

    function __AccessControl_init_unchained() internal onlyInitializing {
    }
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

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

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        StringsUpgradeable.toHexString(uint160(account), 20),
                        " is missing role ",
                        StringsUpgradeable.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

// File: @openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol


// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)

pragma solidity ^0.8.0;





/**
 * @dev Extension of {AccessControl} that allows enumerating the members of each role.
 */
abstract contract AccessControlEnumerableUpgradeable is Initializable, IAccessControlEnumerableUpgradeable, AccessControlUpgradeable {
    function __AccessControlEnumerable_init() internal onlyInitializing {
    }

    function __AccessControlEnumerable_init_unchained() internal onlyInitializing {
    }
    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;

    mapping(bytes32 => EnumerableSetUpgradeable.AddressSet) private _roleMembers;

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

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {
        return _roleMembers[role].at(index);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {
        return _roleMembers[role].length();
    }

    /**
     * @dev Overload {_grantRole} to track enumerable memberships
     */
    function _grantRole(bytes32 role, address account) internal virtual override {
        super._grantRole(role, account);
        _roleMembers[role].add(account);
    }

    /**
     * @dev Overload {_revokeRole} to track enumerable memberships
     */
    function _revokeRole(bytes32 role, address account) internal virtual override {
        super._revokeRole(role, account);
        _roleMembers[role].remove(account);
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

// File: @openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;


/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuardUpgradeable is Initializable {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    function __ReentrancyGuard_init() internal onlyInitializing {
        __ReentrancyGuard_init_unchained();
    }

    function __ReentrancyGuard_init_unchained() internal onlyInitializing {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

// File: SBII721A.sol


// author: yoyoismee.eth -- it's opensource but also feel free to send me coffee/beer.
//  ╔═╗┌─┐┌─┐┌─┐┌┬┐┌┐ ┌─┐┌─┐┌┬┐┌─┐┌┬┐┬ ┬┌┬┐┬┌─┐
//  ╚═╗├─┘├┤ ├┤  ││├┴┐│ │├─┤ │ └─┐ │ │ │ ││││ │
//  ╚═╝┴  └─┘└─┘─┴┘└─┘└─┘┴ ┴ ┴o└─┘ ┴ └─┘─┴┘┴└─┘

pragma solidity 0.8.13;














// @dev speedboat v2 erc721A = modified SBII721A
// @dev should treat this code as experimental.
contract SBII721A is
    Initializable,
    ERC721ASBUpgradable,
    ReentrancyGuardUpgradeable,
    AccessControlEnumerableUpgradeable,
    ISBMintable,
    ISBShipable
{
    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
    using StringsUpgradeable for uint256;
    using SafeERC20 for IERC20;

    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    string public constant MODEL = "SBII-721A-EARLYACCESS";

    struct Round {
        uint128 price;
        uint32 quota;
        uint16 amountPerUser;
        bool isActive;
        bool isPublic;
        bool isMerkleMode; // merkleMode will override price, amountPerUser, and TokenID if specify
        bool exist;
        address tokenAddress; // 0 for base asset
    }

    struct Conf {
        bool allowNFTUpdate;
        bool allowConfUpdate;
        bool allowContract;
        bool allowPrivilege;
        bool randomAccessMode;
        bool allowTarget;
        bool allowLazySell;
        uint64 maxSupply;
    }

    Conf public config;
    string[] public roundNames;

    mapping(bytes32 => EnumerableSetUpgradeable.AddressSet) private walletList;
    mapping(bytes32 => bytes32) private merkleRoot;
    mapping(bytes32 => Round) private roundData;
    mapping(uint256 => bool) private nonceUsed;

    mapping(bytes32 => mapping(address => uint256)) mintedInRound;

    string private _baseTokenURI;
    address private feeReceiver;
    uint256 private bip;
    address public beneficiary;

    function listRole()
        public
        pure
        returns (string[] memory names, bytes32[] memory code)
    {
        names = new string[](2);
        code = new bytes32[](2);

        names[0] = "MINTER";
        names[1] = "ADMIN";

        code[0] = MINTER_ROLE;
        code[1] = DEFAULT_ADMIN_ROLE;
    }

    function grantRoles(bytes32 role, address[] calldata accounts) public {
        for (uint256 i = 0; i < accounts.length; i++) {
            super.grantRole(role, accounts[i]);
        }
    }

    function revokeRoles(bytes32 role, address[] calldata accounts) public {
        for (uint256 i = 0; i < accounts.length; i++) {
            super.revokeRole(role, accounts[i]);
        }
    }

    function setBeneficiary(address _beneficiary)
        public
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        require(beneficiary == address(0), "already set");
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        beneficiary = _beneficiary;
    }

    // 0 = unlimited, can only set once.
    function setMaxSupply(uint64 _maxSupply)
        public
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        require(config.maxSupply == 0, "already set");
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        config.maxSupply = _maxSupply;
    }

    function listRoleWallet(bytes32 role)
        public
        view
        returns (address[] memory roleMembers)
    {
        uint256 count = getRoleMemberCount(role);
        roleMembers = new address[](count);
        for (uint256 i = 0; i < count; i++) {
            roleMembers[i] = getRoleMember(role, i);
        }
    }

    function listToken(address wallet)
        public
        view
        returns (uint256[] memory tokenList)
    {
        return tokensOfOwner(wallet);
    }

    function listRounds() public view returns (string[] memory) {
        return roundNames;
    }

    function roundInfo(string memory roundName)
        public
        view
        returns (Round memory)
    {
        return roundData[keccak256(abi.encodePacked(roundName))];
    }

    function massMint(address[] calldata wallets, uint256[] calldata amount)
        public
    {
        require(config.allowPrivilege, "disabled feature");
        require(hasRole(MINTER_ROLE, msg.sender), "require permission");
        for (uint256 i = 0; i < wallets.length; i++) {
            mintNext(wallets[i], amount[i]);
        }
    }

    function mintNext(address reciever, uint256 amount) public override {
        require(config.allowPrivilege, "disabled feature");
        require(hasRole(MINTER_ROLE, msg.sender), "require permission");
        _mintNext(reciever, amount);
    }

    function _mintNext(address reciever, uint256 amount) internal {
        if (config.maxSupply != 0) {
            require(totalSupply() + amount <= config.maxSupply);
        }
        _mint(reciever, amount); // 721A mint
    }

    function _random(address ad, uint256 num) internal returns (uint256) {
        revert("not supported by 721a la");
    }

    function updateURI(string memory newURI)
        public
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        require(config.allowNFTUpdate, "not available");
        _baseTokenURI = newURI;
    }

    function mintTarget(address reciever, uint256 target) public override {
        revert("not supported by 721a la");
    }

    function requestMint(Round storage thisRound, uint256 amount) internal {
        require(thisRound.isActive, "not active");
        require(thisRound.quota >= amount, "out of stock");
        if (!config.allowContract) {
            require(tx.origin == msg.sender, "not allow contract");
        }
        thisRound.quota -= uint32(amount);
    }

    /// magic overload

    function mint(string memory roundName, uint256 amount)
        public
        payable
        nonReentrant
    {
        bytes32 key = keccak256(abi.encodePacked(roundName));
        Round storage thisRound = roundData[key];

        requestMint(thisRound, amount);

        // require(thisRound.isActive, "not active");
        // require(thisRound.quota >= amount, "out of stock");
        // if (!config.allowContract) {
        //     require(tx.origin == msg.sender, "not allow contract");
        // }
        // thisRound.quota -= uint32(amount);

        require(!thisRound.isMerkleMode, "wrong data");

        if (!thisRound.isPublic) {
            require(walletList[key].contains(msg.sender));
            require(
                mintedInRound[key][msg.sender] + amount <=
                    thisRound.amountPerUser,
                "out of quota"
            );
            mintedInRound[key][msg.sender] += amount;
        } else {
            require(amount <= thisRound.amountPerUser, "nope"); // public round can mint multiple time
        }

        paymentUtil.processPayment(
            thisRound.tokenAddress,
            thisRound.price * amount
        );

        _mintNext(msg.sender, amount);
    }

    function mint(
        string memory roundName,
        address wallet,
        uint256 amount,
        uint256 tokenID,
        uint256 nonce,
        uint256 pricePerUnit,
        address denominatedAsset,
        bytes32[] memory proof
    ) public payable {
        bytes32 key = keccak256(abi.encodePacked(roundName));
        Round storage thisRound = roundData[key];

        requestMint(thisRound, amount);

        // require(thisRound.isActive, "not active");
        // require(thisRound.quota >= amount, "out of quota");
        // thisRound.quota -= uint32(amount);

        require(thisRound.isMerkleMode, "invalid");

        bytes32 data = hash(
            wallet,
            amount,
            tokenID,
            nonce,
            pricePerUnit,
            denominatedAsset,
            address(this),
            block.chainid
        );
        require(_merkleCheck(data, merkleRoot[key], proof), "fail merkle");

        _useNonce(nonce);
        if (wallet != address(0)) {
            require(wallet == msg.sender, "nope");
        }

        require(amount > 0, "pick one"); // such a lazy check lol
        require(tokenID == 0, "nope"); // such a lazy check lol

        paymentUtil.processPayment(denominatedAsset, pricePerUnit * amount);
        _mintNext(wallet, amount);
    }

    function mint(
        address wallet,
        uint256 amount,
        uint256 tokenID,
        uint256 nonce,
        uint256 pricePerUnit,
        address denominatedAsset,
        bytes memory signature
    ) public payable {
        bytes32 data = hash(
            wallet,
            amount,
            tokenID,
            nonce,
            pricePerUnit,
            denominatedAsset,
            address(this),
            block.chainid
        );
        require(config.allowLazySell, "not available");
        require(config.allowPrivilege, "not available");

        require(_verifySig(data, signature));

        _useNonce(nonce);
        if (wallet != address(0)) {
            require(wallet == msg.sender, "nope");
        }

        require(amount > 0, "pick one"); // such a lazy check lol
        require(tokenID == 0, "nope"); // such a lazy check lol

        paymentUtil.processPayment(denominatedAsset, pricePerUnit * amount);
        _mintNext(wallet, amount);
    }

    /// magic overload end

    // this is 721 version. in 20 or 1155 will use the same format but different interpretation
    // wallet = 0 mean any
    // tokenID = 0 mean next
    // amount will overide tokenID
    // denominatedAsset = 0 mean chain token (e.g. eth)
    // chainID is to prevent replay attack

    function hash(
        address wallet,
        uint256 amount,
        uint256 tokenID,
        uint256 nonce,
        uint256 pricePerUnit,
        address denominatedAsset,
        address refPorject,
        uint256 chainID
    ) public pure returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(
                    wallet,
                    amount,
                    tokenID,
                    nonce,
                    pricePerUnit,
                    denominatedAsset,
                    refPorject,
                    chainID
                )
            );
    }

    function _toSignedHash(bytes32 data) internal pure returns (bytes32) {
        return ECDSA.toEthSignedMessageHash(data);
    }

    function _verifySig(bytes32 data, bytes memory signature)
        public
        view
        returns (bool)
    {
        return
            hasRole(MINTER_ROLE, ECDSA.recover(_toSignedHash(data), signature));
    }

    function _merkleCheck(
        bytes32 data,
        bytes32 root,
        bytes32[] memory merkleProof
    ) internal pure returns (bool) {
        return MerkleProof.verify(merkleProof, root, data);
    }

    /// ROUND

    function newRound(
        string memory roundName,
        uint128 _price,
        uint32 _quota,
        uint16 _amountPerUser,
        bool _isActive,
        bool _isPublic,
        bool _isMerkle,
        address _tokenAddress
    ) public onlyRole(DEFAULT_ADMIN_ROLE) {
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        bytes32 key = keccak256(abi.encodePacked(roundName));

        require(!roundData[key].exist, "already exist");
        roundNames.push(roundName);
        roundData[key] = Round({
            price: _price,
            quota: _quota,
            amountPerUser: _amountPerUser,
            isActive: _isActive,
            isPublic: _isPublic,
            isMerkleMode: _isMerkle,
            tokenAddress: _tokenAddress,
            exist: true
        });
    }

    function triggerRound(string memory roundName, bool _isActive)
        public
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        bytes32 key = keccak256(abi.encodePacked(roundName));
        roundData[key].isActive = _isActive;
    }

    function setMerkleRoot(string memory roundName, bytes32 root)
        public
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        bytes32 key = keccak256(abi.encodePacked(roundName));
        merkleRoot[key] = root;
    }

    function updateRound(
        string memory roundName,
        uint128 _price,
        uint32 _quota,
        uint16 _amountPerUser,
        bool _isPublic
    ) public onlyRole(DEFAULT_ADMIN_ROLE) {
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        bytes32 key = keccak256(abi.encodePacked(roundName));
        roundData[key].price = _price;
        roundData[key].quota = _quota;
        roundData[key].amountPerUser = _amountPerUser;
        roundData[key].isPublic = _isPublic;
    }

    function addRoundWallet(string memory roundName, address[] memory wallets)
        public
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        bytes32 key = keccak256(abi.encodePacked(roundName));
        for (uint256 i = 0; i < wallets.length; i++) {
            walletList[key].add(wallets[i]);
        }
    }

    function removeRoundWallet(
        string memory roundName,
        address[] memory wallets
    ) public onlyRole(DEFAULT_ADMIN_ROLE) {
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        bytes32 key = keccak256(abi.encodePacked(roundName));
        for (uint256 i = 0; i < wallets.length; i++) {
            walletList[key].remove(wallets[i]);
        }
    }

    function getRoundWallet(string memory roundName)
        public
        view
        returns (address[] memory)
    {
        return walletList[keccak256(abi.encodePacked(roundName))].values();
    }

    function isQualify(address wallet, string memory roundName)
        public
        view
        returns (bool)
    {
        Round memory x = roundInfo(roundName);
        if (!x.isActive) {
            return false;
        }
        if (x.quota == 0) {
            return false;
        }
        bytes32 key = keccak256(abi.encodePacked(roundName));
        if (!x.isPublic && !walletList[key].contains(wallet)) {
            return false;
        }
        if (mintedInRound[key][wallet] >= x.amountPerUser) {
            return false;
        }
        return true;
    }

    function listQualifiedRound(address wallet)
        public
        view
        returns (string[] memory)
    {
        string[] memory valid = new string[](roundNames.length);
        for (uint256 i = 0; i < roundNames.length; i++) {
            if (isQualify(wallet, roundNames[i])) {
                valid[i] = roundNames[i];
            }
        }
        return valid;
    }

    function burnNonce(uint256[] calldata nonces)
        external
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        require(config.allowPrivilege, "disabled feature");

        for (uint256 i = 0; i < nonces.length; i++) {
            nonceUsed[nonces[i]] = true;
        }
    }

    function resetNonce(uint256[] calldata nonces)
        external
        onlyRole(DEFAULT_ADMIN_ROLE)
    {
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        require(config.allowPrivilege, "disabled feature");

        for (uint256 i = 0; i < nonces.length; i++) {
            nonceUsed[nonces[i]] = false;
        }
    }

    function _useNonce(uint256 nonce) internal {
        require(!nonceUsed[nonce], "used");
        nonceUsed[nonce] = true;
    }

    /// ROUND end ///

    function initialize(
        bytes calldata initArg,
        uint128 _bip,
        address _feeReceiver
    ) public initializer {
        feeReceiver = _feeReceiver;
        bip = _bip;

        (
            string memory name,
            string memory symbol,
            string memory baseTokenURI,
            address owner,
            bool _allowNFTUpdate,
            bool _allowConfUpdate,
            bool _allowContract,
            bool _allowPrivilege,
            bool _randomAccessMode,
            bool _allowTarget,
            bool _allowLazySell
        ) = abi.decode(
                initArg,
                (
                    string,
                    string,
                    string,
                    address,
                    bool,
                    bool,
                    bool,
                    bool,
                    bool,
                    bool,
                    bool
                )
            );

        __721AInit(name, symbol);
        _setupRole(DEFAULT_ADMIN_ROLE, owner);

        _baseTokenURI = baseTokenURI;
        config = Conf({
            allowNFTUpdate: _allowNFTUpdate,
            allowConfUpdate: _allowConfUpdate,
            allowContract: _allowContract,
            allowPrivilege: _allowPrivilege,
            randomAccessMode: _randomAccessMode,
            allowTarget: _allowTarget,
            allowLazySell: _allowLazySell,
            maxSupply: 0
        });
    }

    function updateConfig(
        bool _allowNFTUpdate,
        bool _allowConfUpdate,
        bool _allowContract,
        bool _allowPrivilege,
        bool _allowTarget,
        bool _allowLazySell
    ) public onlyRole(DEFAULT_ADMIN_ROLE) {
        require(config.allowConfUpdate);
        // require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
        config.allowNFTUpdate = _allowNFTUpdate;
        config.allowConfUpdate = _allowConfUpdate;
        config.allowContract = _allowContract;
        config.allowPrivilege = _allowPrivilege;
        config.allowTarget = _allowTarget;
        config.allowLazySell = _allowLazySell;
    }

    function withdraw(address tokenAddress) public nonReentrant {
        address reviver = beneficiary;
        if (beneficiary == address(0)) {
            require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "admin only");
            reviver = msg.sender;
        }
        if (tokenAddress == address(0)) {
            payable(feeReceiver).transfer(
                (address(this).balance * bip) / 10000
            );
            payable(reviver).transfer(address(this).balance);
        } else {
            IERC20 token = IERC20(tokenAddress);
            token.safeTransfer(
                feeReceiver,
                (token.balanceOf(address(this)) * bip) / 10000
            );
            token.safeTransfer(reviver, token.balanceOf(address(this)));
        }
    }

    function contractURI() external view returns (string memory) {
        string memory baseURI = _baseURI();
        return string(abi.encodePacked(baseURI, "contract_uri"));
    }

    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        require(_exists(tokenId), "nonexistent token");

        string memory baseURI = _baseURI();
        return string(abi.encodePacked(baseURI, "uri/", tokenId.toString()));
    }

    // @dev boring section -------------------

    function __721AInit(string memory name, string memory symbol) internal {
        __ReentrancyGuard_init_unchained();
        __ERC721A_init(name, symbol);
        __AccessControlEnumerable_init_unchained();
    }

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

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(AccessControlEnumerableUpgradeable, ERC721ASBUpgradable)
        returns (bool)
    {
        return
            interfaceId == type(IERC721Upgradeable).interfaceId ||
            interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||
            super.supportsInterface(interfaceId);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"AllOwnershipsHaveBeenSet","type":"error"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApprovalToCurrentOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NoTokensMintedYet","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"QuantityMustBeNonZero","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MODEL","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"name":"__ERC721A_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"data","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"_verifySig","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"roundName","type":"string"},{"internalType":"address[]","name":"wallets","type":"address[]"}],"name":"addRoundWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nonces","type":"uint256[]"}],"name":"burnNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"config","outputs":[{"internalType":"bool","name":"allowNFTUpdate","type":"bool"},{"internalType":"bool","name":"allowConfUpdate","type":"bool"},{"internalType":"bool","name":"allowContract","type":"bool"},{"internalType":"bool","name":"allowPrivilege","type":"bool"},{"internalType":"bool","name":"randomAccessMode","type":"bool"},{"internalType":"bool","name":"allowTarget","type":"bool"},{"internalType":"bool","name":"allowLazySell","type":"bool"},{"internalType":"uint64","name":"maxSupply","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"}],"internalType":"struct ERC721ASBUpgradable.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"}],"internalType":"struct ERC721ASBUpgradable.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"roundName","type":"string"}],"name":"getRoundWallet","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"grantRoles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenID","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"pricePerUnit","type":"uint256"},{"internalType":"address","name":"denominatedAsset","type":"address"},{"internalType":"address","name":"refPorject","type":"address"},{"internalType":"uint256","name":"chainID","type":"uint256"}],"name":"hash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"initArg","type":"bytes"},{"internalType":"uint128","name":"_bip","type":"uint128"},{"internalType":"address","name":"_feeReceiver","type":"address"}],"name":"initialize","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":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"string","name":"roundName","type":"string"}],"name":"isQualify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"listQualifiedRound","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"listRole","outputs":[{"internalType":"string[]","name":"names","type":"string[]"},{"internalType":"bytes32[]","name":"code","type":"bytes32[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"listRoleWallet","outputs":[{"internalType":"address[]","name":"roleMembers","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"listRounds","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"listToken","outputs":[{"internalType":"uint256[]","name":"tokenList","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"wallets","type":"address[]"},{"internalType":"uint256[]","name":"amount","type":"uint256[]"}],"name":"massMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"roundName","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenID","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"pricePerUnit","type":"uint256"},{"internalType":"address","name":"denominatedAsset","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"roundName","type":"string"},{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenID","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"pricePerUnit","type":"uint256"},{"internalType":"address","name":"denominatedAsset","type":"address"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"reciever","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintNext","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"reciever","type":"address"},{"internalType":"uint256","name":"target","type":"uint256"}],"name":"mintTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"roundName","type":"string"},{"internalType":"uint128","name":"_price","type":"uint128"},{"internalType":"uint32","name":"_quota","type":"uint32"},{"internalType":"uint16","name":"_amountPerUser","type":"uint16"},{"internalType":"bool","name":"_isActive","type":"bool"},{"internalType":"bool","name":"_isPublic","type":"bool"},{"internalType":"bool","name":"_isMerkle","type":"bool"},{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"newRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nextOwnerToExplicitlySet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"string","name":"roundName","type":"string"},{"internalType":"address[]","name":"wallets","type":"address[]"}],"name":"removeRoundWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nonces","type":"uint256[]"}],"name":"resetNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"revokeRoles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"roundName","type":"string"}],"name":"roundInfo","outputs":[{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint32","name":"quota","type":"uint32"},{"internalType":"uint16","name":"amountPerUser","type":"uint16"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isPublic","type":"bool"},{"internalType":"bool","name":"isMerkleMode","type":"bool"},{"internalType":"bool","name":"exist","type":"bool"},{"internalType":"address","name":"tokenAddress","type":"address"}],"internalType":"struct SBII721A.Round","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"roundNames","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"address","name":"_beneficiary","type":"address"}],"name":"setBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_maxSupply","type":"uint64"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"roundName","type":"string"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"setOwnersExplicit","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":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","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":"string","name":"roundName","type":"string"},{"internalType":"bool","name":"_isActive","type":"bool"}],"name":"triggerRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_allowNFTUpdate","type":"bool"},{"internalType":"bool","name":"_allowConfUpdate","type":"bool"},{"internalType":"bool","name":"_allowContract","type":"bool"},{"internalType":"bool","name":"_allowPrivilege","type":"bool"},{"internalType":"bool","name":"_allowTarget","type":"bool"},{"internalType":"bool","name":"_allowLazySell","type":"bool"}],"name":"updateConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"roundName","type":"string"},{"internalType":"uint128","name":"_price","type":"uint128"},{"internalType":"uint32","name":"_quota","type":"uint32"},{"internalType":"uint16","name":"_amountPerUser","type":"uint16"},{"internalType":"bool","name":"_isPublic","type":"bool"}],"name":"updateRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newURI","type":"string"}],"name":"updateURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50615ed380620000216000396000f3fe6080604052600436106102f45760003560e01c806301ffc9a7146102f9578063056b01ce1461032e57806306fdde0314610343578063081812fc14610365578063095ea7b3146103925780630e4bef5a146103b25780631234170d146103d2578063137fdac0146103f457806318160ddd14610414578063196f0f62146104375780631bb3624c146104575780631c31f710146104775780631fc1e25f1461049757806323b872dd146104c4578063248a9ca3146104e45780632d20fb60146105045780632f2ff15d14610524578063338bd19a1461054457806336568abe14610571578063373f68711461059157806338af3eed146105b15780633f651786146105d257806342842e0e146105f2578063449e14c61461061257806346e410541461062557806351cff8d914610638578063541b47f4146106585780635bbb2177146106785780635e95a47b146106a55780636352211e146106c557806370a08231146106e557806379502c55146107055780637ee5a0a6146107bb578063823b92f7146107db5780638462151c146107fb5780639010d07c1461081b57806391d148541461083b57806395d89b411461085b5780639606d0761461087057806396478cfd1461089057806397d017b6146108b057806398ea1572146108d057806399a2557a146108fd5780639c4f3d0a1461091d5780639d8b44671461093d578063a217fddf1461095d578063a22cb46514610972578063b7582c1a14610992578063b7aafa87146109b5578063b88d4fde146109d5578063bf65df9b146109f5578063c23dc68f14610a15578063c30f4a5a14610a42578063c87b56dd14610a62578063c99323a014610a82578063ca15c87314610aa2578063ce44445c14610ac2578063d2f01f1914610ae2578063d539139314610b02578063d547741f14610b24578063d7224ba014610b44578063deb9a3a214610b5a578063e8a3d48514610b7a578063e985e9c514610b8f578063f4990d9414610bd8578063f7eb983f14610bf8578063fe88a71d14610c39575b600080fd5b34801561030557600080fd5b50610319610314366004614a10565b610c59565b60405190151581526020015b60405180910390f35b61034161033c366004614ae2565b610c9f565b005b34801561034f57600080fd5b50610358610f05565b6040516103259190614b7e565b34801561037157600080fd5b50610385610380366004614b91565b610f97565b6040516103259190614baa565b34801561039e57600080fd5b506103416103ad366004614bd3565b610fdb565b3480156103be57600080fd5b506103586103cd366004614b91565b611068565b3480156103de57600080fd5b506103e7611115565b6040516103259190614c57565b34801561040057600080fd5b5061034161040f366004614c8d565b6111ef565b34801561042057600080fd5b5061042961128b565b604051908152602001610325565b34801561044357600080fd5b50610341610452366004614d99565b611299565b34801561046357600080fd5b50610319610472366004614de4565b6112e7565b34801561048357600080fd5b50610341610492366004614e2a565b611314565b3480156104a357600080fd5b506104b76104b2366004614e2a565b61136e565b6040516103259190614e47565b3480156104d057600080fd5b506103416104df366004614e7f565b611379565b3480156104f057600080fd5b506104296104ff366004614b91565b611384565b34801561051057600080fd5b5061034161051f366004614b91565b611399565b34801561053057600080fd5b5061034161053f366004614ec0565b6114da565b34801561055057600080fd5b5061056461055f366004614ef0565b6114f7565b6040516103259190614f24565b34801561057d57600080fd5b5061034161058c366004614ec0565b61153b565b34801561059d57600080fd5b506103416105ac366004614fc0565b6115b9565b3480156105bd57600080fd5b5061010e54610385906001600160a01b031681565b3480156105de57600080fd5b506103416105ed366004614bd3565b611667565b3480156105fe57600080fd5b5061034161060d366004614e7f565b6116aa565b610341610620366004615043565b6116c5565b6103416106333660046150cb565b611845565b34801561064457600080fd5b50610341610653366004614e2a565b611a3e565b34801561066457600080fd5b506103416106733660046151d1565b611c84565b34801561068457600080fd5b5061069861069336600461528c565b611efe565b604051610325919061533e565b3480156106b157600080fd5b506103416106c0366004615380565b611fb2565b3480156106d157600080fd5b506103856106e0366004614b91565b61204f565b3480156106f157600080fd5b50610429610700366004614e2a565b612061565b34801561071157600080fd5b506101045461076b9060ff80821691610100810482169162010000820481169163010000008104821691600160201b8204811691600160281b8104821691600160301b82041690600160381b90046001600160401b031688565b604080519815158952961515602089015294151595870195909552911515606086015215156080850152151560a084015290151560c08301526001600160401b031660e082015261010001610325565b3480156107c757600080fd5b506103e76107d6366004614e2a565b6120af565b3480156107e757600080fd5b506104296107f6366004615402565b6122a7565b34801561080757600080fd5b506104b7610816366004614e2a565b61231f565b34801561082757600080fd5b5061038561083636600461547e565b612449565b34801561084757600080fd5b50610319610856366004614ec0565b612461565b34801561086757600080fd5b5061035861248c565b34801561087c57600080fd5b5061034161088b3660046154a0565b61249b565b34801561089c57600080fd5b506105646108ab366004614b91565b6126dd565b3480156108bc57600080fd5b506103416108cb366004614bd3565b612788565b3480156108dc57600080fd5b506108f06108eb366004614ef0565b6127f0565b6040516103259190615533565b34801561090957600080fd5b506104b76109183660046155c6565b612907565b34801561092957600080fd5b506103416109383660046155fb565b612ac8565b34801561094957600080fd5b50610341610958366004615624565b612b33565b34801561096957600080fd5b50610429600081565b34801561097e57600080fd5b5061034161098d366004615665565b612bcc565b34801561099e57600080fd5b506109a7612c61565b604051610325929190615693565b3480156109c157600080fd5b506103416109d0366004614ae2565b612d7f565b3480156109e157600080fd5b506103416109f03660046156dd565b612dcc565b348015610a0157600080fd5b50610319610a10366004615748565b612e1c565b348015610a2157600080fd5b50610a35610a30366004614b91565b612f06565b6040516103259190615781565b348015610a4e57600080fd5b50610341610a5d366004614ef0565b612f9b565b348015610a6e57600080fd5b50610358610a7d366004614b91565b612fde565b348015610a8e57600080fd5b50610341610a9d36600461578f565b613067565b348015610aae57600080fd5b50610429610abd366004614b91565b61312a565b348015610ace57600080fd5b50610341610add366004615624565b613141565b348015610aee57600080fd5b50610341610afd3660046157fa565b6131da565b348015610b0e57600080fd5b50610429600080516020615e5e83398151915281565b348015610b3057600080fd5b50610341610b3f366004614ec0565b61321b565b348015610b5057600080fd5b50610429606d5481565b348015610b6657600080fd5b50610341610b75366004614d99565b613238565b348015610b8657600080fd5b50610358613280565b348015610b9b57600080fd5b50610319610baa366004615853565b6001600160a01b039182166000908152606c6020908152604080832093909416825291909152205460ff1690565b348015610be457600080fd5b50610341610bf3366004614c8d565b6132b4565b348015610c0457600080fd5b5061035860405180604001604052806015815260200174534249492d373231412d4541524c5941434345535360581b81525081565b348015610c4557600080fd5b50610341610c54366004615881565b613349565b60006001600160e01b031982166380ac58cd60e01b1480610c8a57506001600160e01b03198216635b5e139f60e01b145b80610c995750610c99826133ad565b92915050565b6002606e5403610cca5760405162461bcd60e51b8152600401610cc1906158c7565b60405180910390fd5b6002606e55604051600090610ce39084906020016158fe565b60408051601f19818403018152918152815160209283012060008181526101089093529120909150610d1581846133d2565b8054600160c01b900460ff1615610d5b5760405162461bcd60e51b815260206004820152600a60248201526977726f6e67206461746160b01b6044820152606401610cc1565b8054600160b81b900460ff16610e3457600082815261010660205260409020610d8490336134fc565b610d8d57600080fd5b8054600083815261010a60209081526040808320338452909152902054600160a01b90910461ffff1690610dc2908590615930565b1115610dff5760405162461bcd60e51b815260206004820152600c60248201526b6f7574206f662071756f746160a01b6044820152606401610cc1565b600082815261010a6020908152604080832033845290915281208054859290610e29908490615930565b90915550610e609050565b8054600160a01b900461ffff16831115610e605760405162461bcd60e51b8152600401610cc190615948565b600181015481547378cf02e302d5a5f09d8ed821cf2cc2942a9e91bd91630b63fe95916001600160a01b0390911690610ea39087906001600160801b0316615966565b6040518363ffffffff1660e01b8152600401610ec0929190615985565b60006040518083038186803b158015610ed857600080fd5b505af4158015610eec573d6000803e3d6000fd5b50505050610efa3384613511565b50506001606e555050565b606060678054610f149061599e565b80601f0160208091040260200160405190810160405280929190818152602001828054610f409061599e565b8015610f8d5780601f10610f6257610100808354040283529160200191610f8d565b820191906000526020600020905b815481529060010190602001808311610f7057829003601f168201915b5050505050905090565b6000610fa282613566565b610fbf576040516333d1c03960e21b815260040160405180910390fd5b506000908152606b60205260409020546001600160a01b031690565b6000610fe68261204f565b9050806001600160a01b0316836001600160a01b03160361101a5760405163250fdee360e21b815260040160405180910390fd5b336001600160a01b0382161480159061103a57506110388133610baa565b155b15611058576040516367d9dca160e11b815260040160405180910390fd5b61106383838361359f565b505050565b610105818154811061107957600080fd5b9060005260206000200160009150905080546110949061599e565b80601f01602080910402602001604051908101604052809291908181526020018280546110c09061599e565b801561110d5780601f106110e25761010080835404028352916020019161110d565b820191906000526020600020905b8154815290600101906020018083116110f057829003601f168201915b505050505081565b6060610105805480602002602001604051908101604052809291908181526020016000905b828210156111e65783829060005260206000200180546111599061599e565b80601f01602080910402602001604051908101604052809291908181526020018280546111859061599e565b80156111d25780601f106111a7576101008083540402835291602001916111d2565b820191906000526020600020905b8154815290600101906020018083116111b557829003601f168201915b50505050508152602001906001019061113a565b50505050905090565b60006111fb81336135fb565b60008360405160200161120e91906158fe565b60405160208183030381529060405280519060200120905060005b835181101561128457611271848281518110611247576112476159d8565b6020026020010151610106600085815260200190815260200160002061365f90919063ffffffff16565b508061127c816159ee565b915050611229565b5050505050565b606654606554036000190190565b60005b818110156112e1576112cf848484848181106112ba576112ba6159d8565b9050602002016020810190610b3f9190614e2a565b806112d9816159ee565b91505061129c565b50505050565b600061130d600080516020615e5e83398151915261085661130786613674565b856136cc565b9392505050565b600061132081336135fb565b61010e546001600160a01b03161561134a5760405162461bcd60e51b8152600401610cc190615a07565b5061010e80546001600160a01b0319166001600160a01b0392909216919091179055565b6060610c998261231f565b6110638383836136e8565b600090815260a0602052604090206001015490565b806000036113ba576040516356be441560e01b815260040160405180910390fd5b6001606554036113dd5760405163c0367cab60e01b815260040160405180910390fd5b606d5460008190036113ed575060015b606554811061140f576040516370e89b1b60e01b815260040160405180910390fd5b606554828201600019810191101561142a5750606554600019015b815b8181116114cf576000818152606960205260409020546001600160a01b031615801561146e5750600081815260696020526040902054600160e01b900460ff16155b156114c757600061147e826138c0565b80516000848152606960209081526040909120805491909301516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b0390921691909117179055505b60010161142c565b50600101606d555050565b6114e382611384565b6114ed81336135fb565b61106383836139d2565b6060610c9961010660008460405160200161151291906158fe565b6040516020818303038152906040528051906020012081526020019081526020016000206139f4565b6001600160a01b03811633146115ab5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610cc1565b6115b58282613a01565b5050565b60006115c581336135fb565b6000866040516020016115d891906158fe565b60408051601f198184030181529181528151602092830120600090815261010890925290208054931515600160b81b0260ff60b81b1961ffff909616600160a01b029590951663ff00ffff60a01b1963ffffffff909716600160801b026001600160a01b03199095166001600160801b0390981697909717939093179490941694909417919091179055505050565b60405162461bcd60e51b81526020600482015260186024820152776e6f7420737570706f727465642062792037323161206c6160401b6044820152606401610cc1565b61106383838360405180602001604052806000815250612dcc565b60006116d788888888888830466122a7565b61010454909150600160301b900460ff166117045760405162461bcd60e51b8152600401610cc190615a2c565b610104546301000000900460ff1661172e5760405162461bcd60e51b8152600401610cc190615a2c565b61173881836112e7565b61174157600080fd5b61174a85613a23565b6001600160a01b03881615611781576001600160a01b03881633146117815760405162461bcd60e51b8152600401610cc190615948565b600087116117a15760405162461bcd60e51b8152600401610cc190615a53565b85156117bf5760405162461bcd60e51b8152600401610cc190615948565b7378cf02e302d5a5f09d8ed821cf2cc2942a9e91bd630b63fe95846117e48a88615966565b6040518363ffffffff1660e01b8152600401611801929190615985565b60006040518083038186803b15801561181957600080fd5b505af415801561182d573d6000803e3d6000fd5b5050505061183b8888613511565b5050505050505050565b60008860405160200161185891906158fe565b60408051601f1981840301815291815281516020928301206000818152610108909352912090915061188a81896133d2565b8054600160c01b900460ff166118cc5760405162461bcd60e51b81526020600482015260076024820152661a5b9d985b1a5960ca1b6044820152606401610cc1565b60006118de8a8a8a8a8a8a30466122a7565b600084815261010760205260409020549091506118fd90829086613a88565b6119375760405162461bcd60e51b815260206004820152600b60248201526a6661696c206d65726b6c6560a81b6044820152606401610cc1565b61194087613a23565b6001600160a01b038a1615611977576001600160a01b038a1633146119775760405162461bcd60e51b8152600401610cc190615948565b600089116119975760405162461bcd60e51b8152600401610cc190615a53565b87156119b55760405162461bcd60e51b8152600401610cc190615948565b7378cf02e302d5a5f09d8ed821cf2cc2942a9e91bd630b63fe95866119da8c8a615966565b6040518363ffffffff1660e01b81526004016119f7929190615985565b60006040518083038186803b158015611a0f57600080fd5b505af4158015611a23573d6000803e3d6000fd5b50505050611a318a8a613511565b5050505050505050505050565b6002606e5403611a605760405162461bcd60e51b8152600401610cc1906158c7565b6002606e5561010e546001600160a01b031680611abe57611a82600033612461565b611abb5760405162461bcd60e51b815260206004820152600a60248201526961646d696e206f6e6c7960b01b6044820152606401610cc1565b50335b6001600160a01b038216611b605761010c5461010d546001600160a01b03909116906108fc9061271090611af29047615966565b611afc9190615a8b565b6040518115909202916000818181858888f19350505050158015611b24573d6000803e3d6000fd5b506040516001600160a01b038216904780156108fc02916000818181858888f19350505050158015611b5a573d6000803e3d6000fd5b50611c7b565b61010c5461010d546040516370a0823160e01b81528492611c08926001600160a01b0391821692612710928616906370a0823190611ba2903090600401614baa565b602060405180830381865afa158015611bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be39190615a9f565b611bed9190615966565b611bf79190615a8b565b6001600160a01b0384169190613a9d565b611c7982826001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611c389190614baa565b602060405180830381865afa158015611c55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf79190615a9f565b505b50506001606e55565b6000611c9081336135fb565b600089604051602001611ca391906158fe565b60408051808303601f1901815291815281516020928301206000818152610108909352912054909150600160c81b900460ff1615611d135760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e48195e1a5cdd609a1b6044820152606401610cc1565b61010580546001810182556000919091528a51611d57917ffc62abc8c0fc47c2d92f5aec99bf8b60f375828e14394d89345cae11a9867371019060208d0190614941565b506040518061010001604052808a6001600160801b031681526020018963ffffffff1681526020018861ffff168152602001871515815260200186151581526020018515158152602001600115158152602001846001600160a01b0316815250610108600083815260200190815260200160002060008201518160000160006101000a8154816001600160801b0302191690836001600160801b0316021790555060208201518160000160106101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160146101000a81548161ffff021916908361ffff16021790555060608201518160000160166101000a81548160ff02191690831515021790555060808201518160000160176101000a81548160ff02191690831515021790555060a08201518160000160186101000a81548160ff02191690831515021790555060c08201518160000160196101000a81548160ff02191690831515021790555060e08201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555090505050505050505050505050565b80516060906000816001600160401b03811115611f1d57611f1d614a2d565b604051908082528060200260200182016040528015611f5657816020015b611f436149c5565b815260200190600190039081611f3b5790505b50905060005b828114611faa57611f85858281518110611f7857611f786159d8565b6020026020010151612f06565b828281518110611f9757611f976159d8565b6020908102919091010152600101611f5c565b509392505050565b6000611fbe81336135fb565b61010454610100900460ff16611fd357600080fd5b50610104805461ffff191696151561ff00191696909617610100951515959095029490941763ffff00001916620100009315159390930263ff0000001916929092176301000000911515919091021761ffff60281b1916600160281b9115159190910260ff60301b191617600160301b91151591909102179055565b600061205a826138c0565b5192915050565b60006001600160a01b03821661208a576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b03166000908152606a60205260409020546001600160401b031690565b610105546060906000906001600160401b038111156120d0576120d0614a2d565b60405190808252806020026020018201604052801561210357816020015b60608152602001906001900390816120ee5790505b50905060005b610105548110156122a0576121c484610105838154811061212c5761212c6159d8565b9060005260206000200180546121419061599e565b80601f016020809104026020016040519081016040528092919081815260200182805461216d9061599e565b80156121ba5780601f1061218f576101008083540402835291602001916121ba565b820191906000526020600020905b81548152906001019060200180831161219d57829003601f168201915b5050505050612e1c565b1561228e5761010581815481106121dd576121dd6159d8565b9060005260206000200180546121f29061599e565b80601f016020809104026020016040519081016040528092919081815260200182805461221e9061599e565b801561226b5780601f106122405761010080835404028352916020019161226b565b820191906000526020600020905b81548152906001019060200180831161224e57829003601f168201915b5050505050828281518110612282576122826159d8565b60200260200101819052505b80612298816159ee565b915050612109565b5092915050565b6040516001600160601b031960608a811b82166020840152603483018a905260548301899052607483018890526094830187905285811b821660b484015284901b1660c882015260dc810182905260009060fc0160405160208183030381529060405280519060200120905098975050505050505050565b6060600080600061232f85612061565b90506000816001600160401b0381111561234b5761234b614a2d565b604051908082528060200260200182016040528015612374578160200160208202803683370190505b50905061237f6149c5565b60015b83861461243d57600081815260696020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff16151591810182905292506124355781516001600160a01b0316156123f657815194505b876001600160a01b0316856001600160a01b0316036124355780838780600101985081518110612428576124286159d8565b6020026020010181815250505b600101612382565b50909695505050505050565b600082815260d26020526040812061130d9083613af3565b600091825260a0602090815260408084206001600160a01b0393909316845291905290205460ff1690565b606060688054610f149061599e565b600054610100900460ff166124b65760005460ff16156124be565b6124be613aff565b6125215760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610cc1565b600054610100900460ff16158015612543576000805461ffff19166101011790555b8161010c60006101000a8154816001600160a01b0302191690836001600160a01b03160217905550826001600160801b031661010d8190555060008060008060008060008060008060008f8f81019061259c9190615ac3565b9a509a509a509a509a509a509a509a509a509a509a506125bc8b8b613b10565b6125c7600089613b2a565b88516125db9061010b9060208c0190614941565b5060408051610100808201835298151580825297151560208201819052961515918101829052941515606086018190529315156080860181905292151560a0860181905291151560c08601819052600060e090960195909552610104805461ffff191661ff001990981697909717959097029490941763ffff000019166201000090960263ff00000019169590951763010000009091021761ffff60201b1916600160201b90940260ff60281b191693909317600160281b90910217600160301b600160781b031916600160301b909202600160381b600160781b0319169190911790555050821591506112849050576000805461ff00191690555050505050565b606060006126ea8361312a565b9050806001600160401b0381111561270457612704614a2d565b60405190808252806020026020018201604052801561272d578160200160208202803683370190505b50915060005b81811015612781576127458482612449565b838281518110612757576127576159d8565b6001600160a01b039092166020928302919091019091015280612779816159ee565b915050612733565b5050919050565b610104546301000000900460ff166127b25760405162461bcd60e51b8152600401610cc190615bd4565b6127ca600080516020615e5e83398151915233612461565b6127e65760405162461bcd60e51b8152600401610cc190615bfe565b6115b58282613511565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915261010860008360405160200161284791906158fe565b60408051601f19818403018152918152815160209283012083528282019390935290820160002082516101008101845281546001600160801b038116825263ffffffff600160801b8204169382019390935261ffff600160a01b8404169381019390935260ff600160b01b8304811615156060850152600160b81b8304811615156080850152600160c01b83048116151560a0850152600160c81b909204909116151560c0830152600101546001600160a01b031660e082015292915050565b606081831061292957604051631960ccad60e11b815260040160405180910390fd5b606554600090600185101561293d57600194505b80841115612949578093505b600061295487612061565b905084861015612973578585038181101561296d578091505b50612977565b5060005b6000816001600160401b0381111561299157612991614a2d565b6040519080825280602002602001820160405280156129ba578160200160208202803683370190505b509050816000036129d057935061130d92505050565b60006129db88612f06565b9050600081604001516129ec575080515b885b8881141580156129fe5750848714155b15612ab757600081815260696020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff1615159181018290529350612aaf5782516001600160a01b031615612a7057825191505b8a6001600160a01b0316826001600160a01b031603612aaf5780848880600101995081518110612aa257612aa26159d8565b6020026020010181815250505b6001016129ee565b505050928352509095945050505050565b6000612ad481336135fb565b61010454600160381b90046001600160401b031615612b055760405162461bcd60e51b8152600401610cc190615a07565b5061010480546001600160401b03909216600160381b02600160381b600160781b0319909216919091179055565b6000612b3f81336135fb565b610104546301000000900460ff16612b695760405162461bcd60e51b8152600401610cc190615bd4565b60005b828110156112e15760006101096000868685818110612b8d57612b8d6159d8565b90506020020135815260200190815260200160002060006101000a81548160ff0219169083151502179055508080612bc4906159ee565b915050612b6c565b336001600160a01b03831603612bf55760405163b06307db60e01b815260040160405180910390fd5b336000818152606c602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6040805160028082526060828101909352829190816020015b6060815260200190600190039081612c7a57505060408051600280825260608201835292945091906020830190803683370190505090506040518060400160405280600681526020016526a4a72a22a960d11b81525082600081518110612ce357612ce36159d8565b60200260200101819052506040518060400160405280600581526020016420a226a4a760d91b81525082600181518110612d1f57612d1f6159d8565b6020026020010181905250600080516020615e5e83398151915281600081518110612d4c57612d4c6159d8565b6020026020010181815250506000801b81600181518110612d6f57612d6f6159d8565b6020026020010181815250509091565b6000612d8b81336135fb565b600083604051602001612d9e91906158fe565b60408051601f1981840301815291815281516020928301206000908152610107909252902092909255505050565b612dd78484846136e8565b612de9836001600160a01b0316613b34565b8015612dfe5750612dfc84848484613b43565b155b156112e1576040516368d2bf6b60e11b815260040160405180910390fd5b600080612e28836127f0565b90508060600151612e3d576000915050610c99565b806020015163ffffffff16600003612e59576000915050610c99565b600083604051602001612e6c91906158fe565b6040516020818303038152906040528051906020012090508160800151158015612eac5750600081815261010660205260409020612eaa90866134fc565b155b15612ebc57600092505050610c99565b604080830151600083815261010a60209081528382206001600160a01b038a1683529052919091205461ffff90911611612efb57600092505050610c99565b506001949350505050565b612f0e6149c5565b612f166149c5565b6001831080612f2757506065548310155b15612f325792915050565b50600082815260696020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff161580159282019290925290612f925792915050565b61130d836138c0565b6000612fa781336135fb565b6101045460ff16612fca5760405162461bcd60e51b8152600401610cc190615a2c565b81516110639061010b906020850190614941565b6060612fe982613566565b6130295760405162461bcd60e51b81526020600482015260116024820152703737b732bc34b9ba32b73a103a37b5b2b760791b6044820152606401610cc1565b6000613033613c2e565b90508061303f84613c3e565b604051602001613050929190615c2a565b604051602081830303815290604052915050919050565b610104546301000000900460ff166130915760405162461bcd60e51b8152600401610cc190615bd4565b6130a9600080516020615e5e83398151915233612461565b6130c55760405162461bcd60e51b8152600401610cc190615bfe565b60005b83811015611284576131188585838181106130e5576130e56159d8565b90506020020160208101906130fa9190614e2a565b84848481811061310c5761310c6159d8565b90506020020135612788565b80613122816159ee565b9150506130c8565b600081815260d260205260408120610c9990613d3e565b600061314d81336135fb565b610104546301000000900460ff166131775760405162461bcd60e51b8152600401610cc190615bd4565b60005b828110156112e1576001610109600086868581811061319b5761319b6159d8565b90506020020135815260200190815260200160002060006101000a81548160ff02191690831515021790555080806131d2906159ee565b91505061317a565b6131e2613d48565b6131ea613d48565b81516131fd906067906020850190614941565b508051613211906068906020840190614941565b5060016065555050565b61322482611384565b61322e81336135fb565b6110638383613a01565b60005b818110156112e15761326e84848484818110613259576132596159d8565b905060200201602081019061053f9190614e2a565b80613278816159ee565b91505061323b565b6060600061328c613c2e565b90508060405160200161329f9190615c69565b60405160208183030381529060405291505090565b60006132c081336135fb565b6000836040516020016132d391906158fe565b60405160208183030381529060405280519060200120905060005b83518110156112845761333684828151811061330c5761330c6159d8565b60200260200101516101066000858152602001908152602001600020613d7190919063ffffffff16565b5080613341816159ee565b9150506132ee565b600061335581336135fb565b60008360405160200161336891906158fe565b60408051601f198184030181529181528151602092830120600090815261010890925290208054931515600160b01b0260ff60b01b1990941693909317909255505050565b60006001600160e01b03198216635a05180f60e01b1480610c995750610c9982613d86565b8154600160b01b900460ff166134175760405162461bcd60e51b815260206004820152600a6024820152696e6f742061637469766560b01b6044820152606401610cc1565b8154600160801b900463ffffffff168111156134645760405162461bcd60e51b815260206004820152600c60248201526b6f7574206f662073746f636b60a01b6044820152606401610cc1565b6101045462010000900460ff166134b9573233146134b95760405162461bcd60e51b81526020600482015260126024820152711b9bdd08185b1b1bddc818dbdb9d1c9858dd60721b6044820152606401610cc1565b8154819083906010906134da908490600160801b900463ffffffff16615c99565b92506101000a81548163ffffffff021916908363ffffffff1602179055505050565b600061130d836001600160a01b038416613dab565b61010454600160381b90046001600160401b03161561355c5761010454600160381b90046001600160401b03168161354761128b565b6135519190615930565b111561355c57600080fd5b6115b58282613dc3565b60008160011115801561357a575060655482105b8015610c99575050600090815260696020526040902054600160e01b900460ff161590565b6000828152606b602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6136058282612461565b6115b55761361d816001600160a01b03166014613ed4565b613628836020613ed4565b604051602001613639929190615cbe565b60408051601f198184030181529082905262461bcd60e51b8252610cc191600401614b7e565b600061130d836001600160a01b03841661406f565b6000610c99826040517b0ca2ba3432b932bab69029b4b3b732b21026b2b9b9b0b3b29d05199960211b6020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b60008060006136db85856140b9565b91509150611faa81614127565b60006136f3826138c0565b9050836001600160a01b031681600001516001600160a01b03161461372a5760405162a1148160e81b815260040160405180910390fd5b6000336001600160a01b038616148061374857506137488533610baa565b8061376357503361375884610f97565b6001600160a01b0316145b90508061378357604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b0384166137aa57604051633a954ecd60e21b815260040160405180910390fd5b6137b66000848761359f565b6001600160a01b038581166000908152606a6020908152604080832080546001600160401b03198082166001600160401b0392831660001901831617909255898616808652838620805493841693831660019081018416949094179055898652606990945282852080546001600160e01b031916909417600160a01b4290921691909102178355870180845292208054919390911661388957606554821461388957805460208601516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b038a16171781555b50505082846001600160a01b0316866001600160a01b0316600080516020615e7e83398151915260405160405180910390a4611284565b6138c86149c5565b81806001111580156138db575060655481105b156139b957600081815260696020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff161515918101829052906139b75780516001600160a01b03161561394e579392505050565b5060001901600081815260696020908152604091829020825160608101845290546001600160a01b038116808352600160a01b82046001600160401b031693830193909352600160e01b900460ff16151592810192909252156139b2579392505050565b61394e565b505b604051636f96cda160e11b815260040160405180910390fd5b6139dc82826142db565b600082815260d260205260409020611063908261365f565b6060600061130d83614361565b613a0b82826143bd565b600082815260d2602052604090206110639082613d71565b6000818152610109602052604090205460ff1615613a6c5760405162461bcd60e51b8152600401610cc1906020808252600490820152631d5cd95960e21b604082015260600190565b600090815261010960205260409020805460ff19166001179055565b6000613a95828486614424565b949350505050565b6110638363a9059cbb60e01b8484604051602401613abc929190615985565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261443a565b600061130d838361450c565b6000613b0a30613b34565b15905090565b613b18614536565b613b2282826131da565b6115b5613d48565b6115b582826139d2565b6001600160a01b03163b151590565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290613b78903390899088908890600401615d2d565b6020604051808303816000875af1925050508015613bb3575060408051601f3d908101601f19168201909252613bb091810190615d6a565b60015b613c11573d808015613be1576040519150601f19603f3d011682016040523d82523d6000602084013e613be6565b606091505b508051600003613c09576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b606061010b8054610f149061599e565b606081600003613c655750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613c8f5780613c79816159ee565b9150613c889050600a83615a8b565b9150613c69565b6000816001600160401b03811115613ca957613ca9614a2d565b6040519080825280601f01601f191660200182016040528015613cd3576020820181803683370190505b5090505b8415613a9557613ce8600183615d87565b9150613cf5600a86615d9e565b613d00906030615930565b60f81b818381518110613d1557613d156159d8565b60200101906001600160f81b031916908160001a905350613d37600a86615a8b565b9450613cd7565b6000610c99825490565b600054610100900460ff16613d6f5760405162461bcd60e51b8152600401610cc190615db2565b565b600061130d836001600160a01b038416614564565b60006001600160e01b03198216637965db0b60e01b1480610c995750610c9982614657565b60009081526001919091016020526040902054151590565b6065546001600160a01b038316613dec57604051622e076360e81b815260040160405180910390fd5b81600003613e0d5760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b0383166000818152606a6020908152604080832080546001600160801b031981166001600160401b038083168a018116918217600160401b6001600160401b031990941690921783900481168a01811690920217909155858452606990925290912080546001600160e01b031916909217600160a01b4290921691909102179055808083015b6040516001830192906001600160a01b03871690600090600080516020615e7e833981519152908290a4808203613e9a5750606555505050565b60606000613ee3836002615966565b613eee906002615930565b6001600160401b03811115613f0557613f05614a2d565b6040519080825280601f01601f191660200182016040528015613f2f576020820181803683370190505b509050600360fc1b81600081518110613f4a57613f4a6159d8565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110613f7957613f796159d8565b60200101906001600160f81b031916908160001a9053506000613f9d846002615966565b613fa8906001615930565b90505b6001811115614020576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613fdc57613fdc6159d8565b1a60f81b828281518110613ff257613ff26159d8565b60200101906001600160f81b031916908160001a90535060049490941c9361401981615dfd565b9050613fab565b50831561130d5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610cc1565b600061407b8383613dab565b6140b157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610c99565b506000610c99565b60008082516041036140ef5760208301516040840151606085015160001a6140e3878285856146a7565b94509450505050614120565b8251604003614118576020830151604084015161410d86838361478a565b935093505050614120565b506000905060025b9250929050565b600081600481111561413b5761413b615e14565b036141435750565b600181600481111561415757614157615e14565b0361419f5760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401610cc1565b60028160048111156141b3576141b3615e14565b036142005760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610cc1565b600381600481111561421457614214615e14565b0361426c5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610cc1565b600481600481111561428057614280615e14565b036142d85760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610cc1565b50565b6142e58282612461565b6115b557600082815260a0602090815260408083206001600160a01b03851684529091529020805460ff1916600117905561431d3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156143b157602002820191906000526020600020905b81548152602001906001019080831161439d575b50505050509050919050565b6143c78282612461565b156115b557600082815260a0602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60008261443185846147c3565b14949350505050565b600061448f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661482f9092919063ffffffff16565b80519091501561106357808060200190518101906144ad9190615e2a565b6110635760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610cc1565b6000826000018281548110614523576145236159d8565b9060005260206000200154905092915050565b600054610100900460ff1661455d5760405162461bcd60e51b8152600401610cc190615db2565b6001606e55565b6000818152600183016020526040812054801561464d576000614588600183615d87565b855490915060009061459c90600190615d87565b90508181146146015760008660000182815481106145bc576145bc6159d8565b90600052602060002001549050808760000184815481106145df576145df6159d8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061461257614612615e47565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610c99565b6000915050610c99565b60006001600160e01b031982166380ac58cd60e01b148061468857506001600160e01b03198216635b5e139f60e01b145b80610c9957506301ffc9a760e01b6001600160e01b0319831614610c99565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b038311156146d45750600090506003614781565b8460ff16601b141580156146ec57508460ff16601c14155b156146fd5750600090506004614781565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614751573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661477a57600060019250925050614781565b9150600090505b94509492505050565b6000806001600160ff1b038316816147a760ff86901c601b615930565b90506147b5878288856146a7565b935093505050935093915050565b600081815b8451811015611faa5760008582815181106147e5576147e56159d8565b6020026020010151905080831161480b576000838152602082905260409020925061481c565b600081815260208490526040902092505b5080614827816159ee565b9150506147c8565b6060613a9584846000858561484385613b34565b61488f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610cc1565b600080866001600160a01b031685876040516148ab91906158fe565b60006040518083038185875af1925050503d80600081146148e8576040519150601f19603f3d011682016040523d82523d6000602084013e6148ed565b606091505b50915091506148fd828286614908565b979650505050505050565b6060831561491757508161130d565b8251156149275782518084602001fd5b8160405162461bcd60e51b8152600401610cc19190614b7e565b82805461494d9061599e565b90600052602060002090601f01602090048101928261496f57600085556149b5565b82601f1061498857805160ff19168380011785556149b5565b828001600101855582156149b5579182015b828111156149b557825182559160200191906001019061499a565b506149c19291506149e5565b5090565b604080516060810182526000808252602082018190529181019190915290565b5b808211156149c157600081556001016149e6565b6001600160e01b0319811681146142d857600080fd5b600060208284031215614a2257600080fd5b813561130d816149fa565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614a6b57614a6b614a2d565b604052919050565b600082601f830112614a8457600080fd5b81356001600160401b03811115614a9d57614a9d614a2d565b614ab0601f8201601f1916602001614a43565b818152846020838601011115614ac557600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215614af557600080fd5b82356001600160401b03811115614b0b57600080fd5b614b1785828601614a73565b95602094909401359450505050565b60005b83811015614b41578181015183820152602001614b29565b838111156112e15750506000910152565b60008151808452614b6a816020860160208601614b26565b601f01601f19169290920160200192915050565b60208152600061130d6020830184614b52565b600060208284031215614ba357600080fd5b5035919050565b6001600160a01b0391909116815260200190565b6001600160a01b03811681146142d857600080fd5b60008060408385031215614be657600080fd5b8235614bf181614bbe565b946020939093013593505050565b600082825180855260208086019550808260051b84010181860160005b84811015614c4a57601f19868403018952614c38838351614b52565b98840198925090830190600101614c1c565b5090979650505050505050565b60208152600061130d6020830184614bff565b60006001600160401b03821115614c8357614c83614a2d565b5060051b60200190565b60008060408385031215614ca057600080fd5b82356001600160401b0380821115614cb757600080fd5b614cc386838701614a73565b9350602091508185013581811115614cda57600080fd5b85019050601f81018613614ced57600080fd5b8035614d00614cfb82614c6a565b614a43565b81815260059190911b82018301908381019088831115614d1f57600080fd5b928401925b82841015614d46578335614d3781614bbe565b82529284019290840190614d24565b80955050505050509250929050565b60008083601f840112614d6757600080fd5b5081356001600160401b03811115614d7e57600080fd5b6020830191508360208260051b850101111561412057600080fd5b600080600060408486031215614dae57600080fd5b8335925060208401356001600160401b03811115614dcb57600080fd5b614dd786828701614d55565b9497909650939450505050565b60008060408385031215614df757600080fd5b8235915060208301356001600160401b03811115614e1457600080fd5b614e2085828601614a73565b9150509250929050565b600060208284031215614e3c57600080fd5b813561130d81614bbe565b6020808252825182820181905260009190848201906040850190845b8181101561243d57835183529284019291840191600101614e63565b600080600060608486031215614e9457600080fd5b8335614e9f81614bbe565b92506020840135614eaf81614bbe565b929592945050506040919091013590565b60008060408385031215614ed357600080fd5b823591506020830135614ee581614bbe565b809150509250929050565b600060208284031215614f0257600080fd5b81356001600160401b03811115614f1857600080fd5b613a9584828501614a73565b6020808252825182820181905260009190848201906040850190845b8181101561243d5783516001600160a01b031683529284019291840191600101614f40565b80356001600160801b0381168114614f7c57600080fd5b919050565b803563ffffffff81168114614f7c57600080fd5b803561ffff81168114614f7c57600080fd5b80151581146142d857600080fd5b8035614f7c81614fa7565b600080600080600060a08688031215614fd857600080fd5b85356001600160401b03811115614fee57600080fd5b614ffa88828901614a73565b95505061500960208701614f65565b935061501760408701614f81565b925061502560608701614f95565b9150608086013561503581614fa7565b809150509295509295909350565b600080600080600080600060e0888a03121561505e57600080fd5b873561506981614bbe565b96506020880135955060408801359450606088013593506080880135925060a088013561509581614bbe565b915060c08801356001600160401b038111156150b057600080fd5b6150bc8a828b01614a73565b91505092959891949750929550565b600080600080600080600080610100898b0312156150e857600080fd5b88356001600160401b03808211156150ff57600080fd5b61510b8c838d01614a73565b995060209150818b013561511e81614bbe565b985060408b0135975060608b0135965060808b0135955060a08b0135945060c08b013561514a81614bbe565b935060e08b01358181111561515e57600080fd5b8b019050601f81018c1361517157600080fd5b803561517f614cfb82614c6a565b81815260059190911b8201830190838101908e83111561519e57600080fd5b928401925b828410156151bc578335825292840192908401906151a3565b80955050505050509295985092959890939650565b600080600080600080600080610100898b0312156151ee57600080fd5b88356001600160401b0381111561520457600080fd5b6152108b828c01614a73565b98505061521f60208a01614f65565b965061522d60408a01614f81565b955061523b60608a01614f95565b9450608089013561524b81614fa7565b935060a089013561525b81614fa7565b925060c089013561526b81614fa7565b915060e089013561527b81614bbe565b809150509295985092959890939650565b6000602080838503121561529f57600080fd5b82356001600160401b038111156152b557600080fd5b8301601f810185136152c657600080fd5b80356152d4614cfb82614c6a565b81815260059190911b820183019083810190878311156152f357600080fd5b928401925b828410156148fd578335825292840192908401906152f8565b80516001600160a01b031682526020808201516001600160401b0316908301526040908101511515910152565b6020808252825182820181905260009190848201906040850190845b8181101561243d5761536d838551615311565b928401926060929092019160010161535a565b60008060008060008060c0878903121561539957600080fd5b86356153a481614fa7565b955060208701356153b481614fa7565b945060408701356153c481614fa7565b935060608701356153d481614fa7565b925060808701356153e481614fa7565b915060a08701356153f481614fa7565b809150509295509295509295565b600080600080600080600080610100898b03121561541f57600080fd5b883561542a81614bbe565b97506020890135965060408901359550606089013594506080890135935060a089013561545681614bbe565b925060c089013561546681614bbe565b8092505060e089013590509295985092959890939650565b6000806040838503121561549157600080fd5b50508035926020909101359150565b600080600080606085870312156154b657600080fd5b84356001600160401b03808211156154cd57600080fd5b818701915087601f8301126154e157600080fd5b8135818111156154f057600080fd5b88602082850101111561550257600080fd5b6020928301965094506155189187019050614f65565b9150604085013561552881614bbe565b939692955090935050565b81516001600160801b0316815260208083015163ffffffff169082015260408083015161ffff16908201526060808301511515908201526080828101516101008301916155839084018215159052565b5060a083015161559760a084018215159052565b5060c08301516155ab60c084018215159052565b5060e08301516122a060e08401826001600160a01b03169052565b6000806000606084860312156155db57600080fd5b83356155e681614bbe565b95602085013595506040909401359392505050565b60006020828403121561560d57600080fd5b81356001600160401b038116811461130d57600080fd5b6000806020838503121561563757600080fd5b82356001600160401b0381111561564d57600080fd5b61565985828601614d55565b90969095509350505050565b6000806040838503121561567857600080fd5b823561568381614bbe565b91506020830135614ee581614fa7565b6040815260006156a66040830185614bff565b82810360208481019190915284518083528582019282019060005b81811015614c4a578451835293830193918301916001016156c1565b600080600080608085870312156156f357600080fd5b84356156fe81614bbe565b9350602085013561570e81614bbe565b92506040850135915060608501356001600160401b0381111561573057600080fd5b61573c87828801614a73565b91505092959194509250565b6000806040838503121561575b57600080fd5b823561576681614bbe565b915060208301356001600160401b03811115614e1457600080fd5b60608101610c998284615311565b600080600080604085870312156157a557600080fd5b84356001600160401b03808211156157bc57600080fd5b6157c888838901614d55565b909650945060208701359150808211156157e157600080fd5b506157ee87828801614d55565b95989497509550505050565b6000806040838503121561580d57600080fd5b82356001600160401b038082111561582457600080fd5b61583086838701614a73565b9350602085013591508082111561584657600080fd5b50614e2085828601614a73565b6000806040838503121561586657600080fd5b823561587181614bbe565b91506020830135614ee581614bbe565b6000806040838503121561589457600080fd5b82356001600160401b038111156158aa57600080fd5b6158b685828601614a73565b9250506020830135614ee581614fa7565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60008251615910818460208701614b26565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b600082198211156159435761594361591a565b500190565b6020808252600490820152636e6f706560e01b604082015260600190565b60008160001904831182151516156159805761598061591a565b500290565b6001600160a01b03929092168252602082015260400190565b600181811c908216806159b257607f821691505b6020821081036159d257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b600060018201615a0057615a0061591a565b5060010190565b6020808252600b908201526a185b1c9958591e481cd95d60aa1b604082015260600190565b6020808252600d908201526c6e6f7420617661696c61626c6560981b604082015260600190565b6020808252600890820152677069636b206f6e6560c01b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082615a9a57615a9a615a75565b500490565b600060208284031215615ab157600080fd5b5051919050565b8035614f7c81614bbe565b60008060008060008060008060008060006101608c8e031215615ae557600080fd5b6001600160401b038c35811015615afb57600080fd5b615b088e8e358f01614a73565b9b508060208e01351115615b1b57600080fd5b615b2b8e60208f01358f01614a73565b9a508060408e01351115615b3e57600080fd5b50615b4f8d60408e01358e01614a73565b9850615b5d60608d01615ab8565b9750615b6b60808d01614fb5565b9650615b7960a08d01614fb5565b9550615b8760c08d01614fb5565b9450615b9560e08d01614fb5565b9350615ba46101008d01614fb5565b9250615bb36101208d01614fb5565b9150615bc26101408d01614fb5565b90509295989b509295989b9093969950565b60208082526010908201526f64697361626c6564206665617475726560801b604082015260600190565b6020808252601290820152713932b8bab4b932903832b936b4b9b9b4b7b760711b604082015260600190565b60008351615c3c818460208801614b26565b637572692f60e01b9083019081528351615c5d816004840160208801614b26565b01600401949350505050565b60008251615c7b818460208701614b26565b6b636f6e74726163745f75726960a01b920191825250600c01919050565b600063ffffffff83811690831681811015615cb657615cb661591a565b039392505050565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b815260008351615cf0816017850160208801614b26565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351615d21816028840160208801614b26565b01602801949350505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615d6090830184614b52565b9695505050505050565b600060208284031215615d7c57600080fd5b815161130d816149fa565b600082821015615d9957615d9961591a565b500390565b600082615dad57615dad615a75565b500690565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600081615e0c57615e0c61591a565b506000190190565b634e487b7160e01b600052602160045260246000fd5b600060208284031215615e3c57600080fd5b815161130d81614fa7565b634e487b7160e01b600052603160045260246000fdfe9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220af6b4159ab96119157615b59739f8944ca587d5daa6e0a73833a9a91306c283764736f6c634300080d0033

Deployed Bytecode

0x6080604052600436106102f45760003560e01c806301ffc9a7146102f9578063056b01ce1461032e57806306fdde0314610343578063081812fc14610365578063095ea7b3146103925780630e4bef5a146103b25780631234170d146103d2578063137fdac0146103f457806318160ddd14610414578063196f0f62146104375780631bb3624c146104575780631c31f710146104775780631fc1e25f1461049757806323b872dd146104c4578063248a9ca3146104e45780632d20fb60146105045780632f2ff15d14610524578063338bd19a1461054457806336568abe14610571578063373f68711461059157806338af3eed146105b15780633f651786146105d257806342842e0e146105f2578063449e14c61461061257806346e410541461062557806351cff8d914610638578063541b47f4146106585780635bbb2177146106785780635e95a47b146106a55780636352211e146106c557806370a08231146106e557806379502c55146107055780637ee5a0a6146107bb578063823b92f7146107db5780638462151c146107fb5780639010d07c1461081b57806391d148541461083b57806395d89b411461085b5780639606d0761461087057806396478cfd1461089057806397d017b6146108b057806398ea1572146108d057806399a2557a146108fd5780639c4f3d0a1461091d5780639d8b44671461093d578063a217fddf1461095d578063a22cb46514610972578063b7582c1a14610992578063b7aafa87146109b5578063b88d4fde146109d5578063bf65df9b146109f5578063c23dc68f14610a15578063c30f4a5a14610a42578063c87b56dd14610a62578063c99323a014610a82578063ca15c87314610aa2578063ce44445c14610ac2578063d2f01f1914610ae2578063d539139314610b02578063d547741f14610b24578063d7224ba014610b44578063deb9a3a214610b5a578063e8a3d48514610b7a578063e985e9c514610b8f578063f4990d9414610bd8578063f7eb983f14610bf8578063fe88a71d14610c39575b600080fd5b34801561030557600080fd5b50610319610314366004614a10565b610c59565b60405190151581526020015b60405180910390f35b61034161033c366004614ae2565b610c9f565b005b34801561034f57600080fd5b50610358610f05565b6040516103259190614b7e565b34801561037157600080fd5b50610385610380366004614b91565b610f97565b6040516103259190614baa565b34801561039e57600080fd5b506103416103ad366004614bd3565b610fdb565b3480156103be57600080fd5b506103586103cd366004614b91565b611068565b3480156103de57600080fd5b506103e7611115565b6040516103259190614c57565b34801561040057600080fd5b5061034161040f366004614c8d565b6111ef565b34801561042057600080fd5b5061042961128b565b604051908152602001610325565b34801561044357600080fd5b50610341610452366004614d99565b611299565b34801561046357600080fd5b50610319610472366004614de4565b6112e7565b34801561048357600080fd5b50610341610492366004614e2a565b611314565b3480156104a357600080fd5b506104b76104b2366004614e2a565b61136e565b6040516103259190614e47565b3480156104d057600080fd5b506103416104df366004614e7f565b611379565b3480156104f057600080fd5b506104296104ff366004614b91565b611384565b34801561051057600080fd5b5061034161051f366004614b91565b611399565b34801561053057600080fd5b5061034161053f366004614ec0565b6114da565b34801561055057600080fd5b5061056461055f366004614ef0565b6114f7565b6040516103259190614f24565b34801561057d57600080fd5b5061034161058c366004614ec0565b61153b565b34801561059d57600080fd5b506103416105ac366004614fc0565b6115b9565b3480156105bd57600080fd5b5061010e54610385906001600160a01b031681565b3480156105de57600080fd5b506103416105ed366004614bd3565b611667565b3480156105fe57600080fd5b5061034161060d366004614e7f565b6116aa565b610341610620366004615043565b6116c5565b6103416106333660046150cb565b611845565b34801561064457600080fd5b50610341610653366004614e2a565b611a3e565b34801561066457600080fd5b506103416106733660046151d1565b611c84565b34801561068457600080fd5b5061069861069336600461528c565b611efe565b604051610325919061533e565b3480156106b157600080fd5b506103416106c0366004615380565b611fb2565b3480156106d157600080fd5b506103856106e0366004614b91565b61204f565b3480156106f157600080fd5b50610429610700366004614e2a565b612061565b34801561071157600080fd5b506101045461076b9060ff80821691610100810482169162010000820481169163010000008104821691600160201b8204811691600160281b8104821691600160301b82041690600160381b90046001600160401b031688565b604080519815158952961515602089015294151595870195909552911515606086015215156080850152151560a084015290151560c08301526001600160401b031660e082015261010001610325565b3480156107c757600080fd5b506103e76107d6366004614e2a565b6120af565b3480156107e757600080fd5b506104296107f6366004615402565b6122a7565b34801561080757600080fd5b506104b7610816366004614e2a565b61231f565b34801561082757600080fd5b5061038561083636600461547e565b612449565b34801561084757600080fd5b50610319610856366004614ec0565b612461565b34801561086757600080fd5b5061035861248c565b34801561087c57600080fd5b5061034161088b3660046154a0565b61249b565b34801561089c57600080fd5b506105646108ab366004614b91565b6126dd565b3480156108bc57600080fd5b506103416108cb366004614bd3565b612788565b3480156108dc57600080fd5b506108f06108eb366004614ef0565b6127f0565b6040516103259190615533565b34801561090957600080fd5b506104b76109183660046155c6565b612907565b34801561092957600080fd5b506103416109383660046155fb565b612ac8565b34801561094957600080fd5b50610341610958366004615624565b612b33565b34801561096957600080fd5b50610429600081565b34801561097e57600080fd5b5061034161098d366004615665565b612bcc565b34801561099e57600080fd5b506109a7612c61565b604051610325929190615693565b3480156109c157600080fd5b506103416109d0366004614ae2565b612d7f565b3480156109e157600080fd5b506103416109f03660046156dd565b612dcc565b348015610a0157600080fd5b50610319610a10366004615748565b612e1c565b348015610a2157600080fd5b50610a35610a30366004614b91565b612f06565b6040516103259190615781565b348015610a4e57600080fd5b50610341610a5d366004614ef0565b612f9b565b348015610a6e57600080fd5b50610358610a7d366004614b91565b612fde565b348015610a8e57600080fd5b50610341610a9d36600461578f565b613067565b348015610aae57600080fd5b50610429610abd366004614b91565b61312a565b348015610ace57600080fd5b50610341610add366004615624565b613141565b348015610aee57600080fd5b50610341610afd3660046157fa565b6131da565b348015610b0e57600080fd5b50610429600080516020615e5e83398151915281565b348015610b3057600080fd5b50610341610b3f366004614ec0565b61321b565b348015610b5057600080fd5b50610429606d5481565b348015610b6657600080fd5b50610341610b75366004614d99565b613238565b348015610b8657600080fd5b50610358613280565b348015610b9b57600080fd5b50610319610baa366004615853565b6001600160a01b039182166000908152606c6020908152604080832093909416825291909152205460ff1690565b348015610be457600080fd5b50610341610bf3366004614c8d565b6132b4565b348015610c0457600080fd5b5061035860405180604001604052806015815260200174534249492d373231412d4541524c5941434345535360581b81525081565b348015610c4557600080fd5b50610341610c54366004615881565b613349565b60006001600160e01b031982166380ac58cd60e01b1480610c8a57506001600160e01b03198216635b5e139f60e01b145b80610c995750610c99826133ad565b92915050565b6002606e5403610cca5760405162461bcd60e51b8152600401610cc1906158c7565b60405180910390fd5b6002606e55604051600090610ce39084906020016158fe565b60408051601f19818403018152918152815160209283012060008181526101089093529120909150610d1581846133d2565b8054600160c01b900460ff1615610d5b5760405162461bcd60e51b815260206004820152600a60248201526977726f6e67206461746160b01b6044820152606401610cc1565b8054600160b81b900460ff16610e3457600082815261010660205260409020610d8490336134fc565b610d8d57600080fd5b8054600083815261010a60209081526040808320338452909152902054600160a01b90910461ffff1690610dc2908590615930565b1115610dff5760405162461bcd60e51b815260206004820152600c60248201526b6f7574206f662071756f746160a01b6044820152606401610cc1565b600082815261010a6020908152604080832033845290915281208054859290610e29908490615930565b90915550610e609050565b8054600160a01b900461ffff16831115610e605760405162461bcd60e51b8152600401610cc190615948565b600181015481547378cf02e302d5a5f09d8ed821cf2cc2942a9e91bd91630b63fe95916001600160a01b0390911690610ea39087906001600160801b0316615966565b6040518363ffffffff1660e01b8152600401610ec0929190615985565b60006040518083038186803b158015610ed857600080fd5b505af4158015610eec573d6000803e3d6000fd5b50505050610efa3384613511565b50506001606e555050565b606060678054610f149061599e565b80601f0160208091040260200160405190810160405280929190818152602001828054610f409061599e565b8015610f8d5780601f10610f6257610100808354040283529160200191610f8d565b820191906000526020600020905b815481529060010190602001808311610f7057829003601f168201915b5050505050905090565b6000610fa282613566565b610fbf576040516333d1c03960e21b815260040160405180910390fd5b506000908152606b60205260409020546001600160a01b031690565b6000610fe68261204f565b9050806001600160a01b0316836001600160a01b03160361101a5760405163250fdee360e21b815260040160405180910390fd5b336001600160a01b0382161480159061103a57506110388133610baa565b155b15611058576040516367d9dca160e11b815260040160405180910390fd5b61106383838361359f565b505050565b610105818154811061107957600080fd5b9060005260206000200160009150905080546110949061599e565b80601f01602080910402602001604051908101604052809291908181526020018280546110c09061599e565b801561110d5780601f106110e25761010080835404028352916020019161110d565b820191906000526020600020905b8154815290600101906020018083116110f057829003601f168201915b505050505081565b6060610105805480602002602001604051908101604052809291908181526020016000905b828210156111e65783829060005260206000200180546111599061599e565b80601f01602080910402602001604051908101604052809291908181526020018280546111859061599e565b80156111d25780601f106111a7576101008083540402835291602001916111d2565b820191906000526020600020905b8154815290600101906020018083116111b557829003601f168201915b50505050508152602001906001019061113a565b50505050905090565b60006111fb81336135fb565b60008360405160200161120e91906158fe565b60405160208183030381529060405280519060200120905060005b835181101561128457611271848281518110611247576112476159d8565b6020026020010151610106600085815260200190815260200160002061365f90919063ffffffff16565b508061127c816159ee565b915050611229565b5050505050565b606654606554036000190190565b60005b818110156112e1576112cf848484848181106112ba576112ba6159d8565b9050602002016020810190610b3f9190614e2a565b806112d9816159ee565b91505061129c565b50505050565b600061130d600080516020615e5e83398151915261085661130786613674565b856136cc565b9392505050565b600061132081336135fb565b61010e546001600160a01b03161561134a5760405162461bcd60e51b8152600401610cc190615a07565b5061010e80546001600160a01b0319166001600160a01b0392909216919091179055565b6060610c998261231f565b6110638383836136e8565b600090815260a0602052604090206001015490565b806000036113ba576040516356be441560e01b815260040160405180910390fd5b6001606554036113dd5760405163c0367cab60e01b815260040160405180910390fd5b606d5460008190036113ed575060015b606554811061140f576040516370e89b1b60e01b815260040160405180910390fd5b606554828201600019810191101561142a5750606554600019015b815b8181116114cf576000818152606960205260409020546001600160a01b031615801561146e5750600081815260696020526040902054600160e01b900460ff16155b156114c757600061147e826138c0565b80516000848152606960209081526040909120805491909301516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b0390921691909117179055505b60010161142c565b50600101606d555050565b6114e382611384565b6114ed81336135fb565b61106383836139d2565b6060610c9961010660008460405160200161151291906158fe565b6040516020818303038152906040528051906020012081526020019081526020016000206139f4565b6001600160a01b03811633146115ab5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610cc1565b6115b58282613a01565b5050565b60006115c581336135fb565b6000866040516020016115d891906158fe565b60408051601f198184030181529181528151602092830120600090815261010890925290208054931515600160b81b0260ff60b81b1961ffff909616600160a01b029590951663ff00ffff60a01b1963ffffffff909716600160801b026001600160a01b03199095166001600160801b0390981697909717939093179490941694909417919091179055505050565b60405162461bcd60e51b81526020600482015260186024820152776e6f7420737570706f727465642062792037323161206c6160401b6044820152606401610cc1565b61106383838360405180602001604052806000815250612dcc565b60006116d788888888888830466122a7565b61010454909150600160301b900460ff166117045760405162461bcd60e51b8152600401610cc190615a2c565b610104546301000000900460ff1661172e5760405162461bcd60e51b8152600401610cc190615a2c565b61173881836112e7565b61174157600080fd5b61174a85613a23565b6001600160a01b03881615611781576001600160a01b03881633146117815760405162461bcd60e51b8152600401610cc190615948565b600087116117a15760405162461bcd60e51b8152600401610cc190615a53565b85156117bf5760405162461bcd60e51b8152600401610cc190615948565b7378cf02e302d5a5f09d8ed821cf2cc2942a9e91bd630b63fe95846117e48a88615966565b6040518363ffffffff1660e01b8152600401611801929190615985565b60006040518083038186803b15801561181957600080fd5b505af415801561182d573d6000803e3d6000fd5b5050505061183b8888613511565b5050505050505050565b60008860405160200161185891906158fe565b60408051601f1981840301815291815281516020928301206000818152610108909352912090915061188a81896133d2565b8054600160c01b900460ff166118cc5760405162461bcd60e51b81526020600482015260076024820152661a5b9d985b1a5960ca1b6044820152606401610cc1565b60006118de8a8a8a8a8a8a30466122a7565b600084815261010760205260409020549091506118fd90829086613a88565b6119375760405162461bcd60e51b815260206004820152600b60248201526a6661696c206d65726b6c6560a81b6044820152606401610cc1565b61194087613a23565b6001600160a01b038a1615611977576001600160a01b038a1633146119775760405162461bcd60e51b8152600401610cc190615948565b600089116119975760405162461bcd60e51b8152600401610cc190615a53565b87156119b55760405162461bcd60e51b8152600401610cc190615948565b7378cf02e302d5a5f09d8ed821cf2cc2942a9e91bd630b63fe95866119da8c8a615966565b6040518363ffffffff1660e01b81526004016119f7929190615985565b60006040518083038186803b158015611a0f57600080fd5b505af4158015611a23573d6000803e3d6000fd5b50505050611a318a8a613511565b5050505050505050505050565b6002606e5403611a605760405162461bcd60e51b8152600401610cc1906158c7565b6002606e5561010e546001600160a01b031680611abe57611a82600033612461565b611abb5760405162461bcd60e51b815260206004820152600a60248201526961646d696e206f6e6c7960b01b6044820152606401610cc1565b50335b6001600160a01b038216611b605761010c5461010d546001600160a01b03909116906108fc9061271090611af29047615966565b611afc9190615a8b565b6040518115909202916000818181858888f19350505050158015611b24573d6000803e3d6000fd5b506040516001600160a01b038216904780156108fc02916000818181858888f19350505050158015611b5a573d6000803e3d6000fd5b50611c7b565b61010c5461010d546040516370a0823160e01b81528492611c08926001600160a01b0391821692612710928616906370a0823190611ba2903090600401614baa565b602060405180830381865afa158015611bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be39190615a9f565b611bed9190615966565b611bf79190615a8b565b6001600160a01b0384169190613a9d565b611c7982826001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611c389190614baa565b602060405180830381865afa158015611c55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf79190615a9f565b505b50506001606e55565b6000611c9081336135fb565b600089604051602001611ca391906158fe565b60408051808303601f1901815291815281516020928301206000818152610108909352912054909150600160c81b900460ff1615611d135760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e48195e1a5cdd609a1b6044820152606401610cc1565b61010580546001810182556000919091528a51611d57917ffc62abc8c0fc47c2d92f5aec99bf8b60f375828e14394d89345cae11a9867371019060208d0190614941565b506040518061010001604052808a6001600160801b031681526020018963ffffffff1681526020018861ffff168152602001871515815260200186151581526020018515158152602001600115158152602001846001600160a01b0316815250610108600083815260200190815260200160002060008201518160000160006101000a8154816001600160801b0302191690836001600160801b0316021790555060208201518160000160106101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160146101000a81548161ffff021916908361ffff16021790555060608201518160000160166101000a81548160ff02191690831515021790555060808201518160000160176101000a81548160ff02191690831515021790555060a08201518160000160186101000a81548160ff02191690831515021790555060c08201518160000160196101000a81548160ff02191690831515021790555060e08201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555090505050505050505050505050565b80516060906000816001600160401b03811115611f1d57611f1d614a2d565b604051908082528060200260200182016040528015611f5657816020015b611f436149c5565b815260200190600190039081611f3b5790505b50905060005b828114611faa57611f85858281518110611f7857611f786159d8565b6020026020010151612f06565b828281518110611f9757611f976159d8565b6020908102919091010152600101611f5c565b509392505050565b6000611fbe81336135fb565b61010454610100900460ff16611fd357600080fd5b50610104805461ffff191696151561ff00191696909617610100951515959095029490941763ffff00001916620100009315159390930263ff0000001916929092176301000000911515919091021761ffff60281b1916600160281b9115159190910260ff60301b191617600160301b91151591909102179055565b600061205a826138c0565b5192915050565b60006001600160a01b03821661208a576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b03166000908152606a60205260409020546001600160401b031690565b610105546060906000906001600160401b038111156120d0576120d0614a2d565b60405190808252806020026020018201604052801561210357816020015b60608152602001906001900390816120ee5790505b50905060005b610105548110156122a0576121c484610105838154811061212c5761212c6159d8565b9060005260206000200180546121419061599e565b80601f016020809104026020016040519081016040528092919081815260200182805461216d9061599e565b80156121ba5780601f1061218f576101008083540402835291602001916121ba565b820191906000526020600020905b81548152906001019060200180831161219d57829003601f168201915b5050505050612e1c565b1561228e5761010581815481106121dd576121dd6159d8565b9060005260206000200180546121f29061599e565b80601f016020809104026020016040519081016040528092919081815260200182805461221e9061599e565b801561226b5780601f106122405761010080835404028352916020019161226b565b820191906000526020600020905b81548152906001019060200180831161224e57829003601f168201915b5050505050828281518110612282576122826159d8565b60200260200101819052505b80612298816159ee565b915050612109565b5092915050565b6040516001600160601b031960608a811b82166020840152603483018a905260548301899052607483018890526094830187905285811b821660b484015284901b1660c882015260dc810182905260009060fc0160405160208183030381529060405280519060200120905098975050505050505050565b6060600080600061232f85612061565b90506000816001600160401b0381111561234b5761234b614a2d565b604051908082528060200260200182016040528015612374578160200160208202803683370190505b50905061237f6149c5565b60015b83861461243d57600081815260696020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff16151591810182905292506124355781516001600160a01b0316156123f657815194505b876001600160a01b0316856001600160a01b0316036124355780838780600101985081518110612428576124286159d8565b6020026020010181815250505b600101612382565b50909695505050505050565b600082815260d26020526040812061130d9083613af3565b600091825260a0602090815260408084206001600160a01b0393909316845291905290205460ff1690565b606060688054610f149061599e565b600054610100900460ff166124b65760005460ff16156124be565b6124be613aff565b6125215760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610cc1565b600054610100900460ff16158015612543576000805461ffff19166101011790555b8161010c60006101000a8154816001600160a01b0302191690836001600160a01b03160217905550826001600160801b031661010d8190555060008060008060008060008060008060008f8f81019061259c9190615ac3565b9a509a509a509a509a509a509a509a509a509a509a506125bc8b8b613b10565b6125c7600089613b2a565b88516125db9061010b9060208c0190614941565b5060408051610100808201835298151580825297151560208201819052961515918101829052941515606086018190529315156080860181905292151560a0860181905291151560c08601819052600060e090960195909552610104805461ffff191661ff001990981697909717959097029490941763ffff000019166201000090960263ff00000019169590951763010000009091021761ffff60201b1916600160201b90940260ff60281b191693909317600160281b90910217600160301b600160781b031916600160301b909202600160381b600160781b0319169190911790555050821591506112849050576000805461ff00191690555050505050565b606060006126ea8361312a565b9050806001600160401b0381111561270457612704614a2d565b60405190808252806020026020018201604052801561272d578160200160208202803683370190505b50915060005b81811015612781576127458482612449565b838281518110612757576127576159d8565b6001600160a01b039092166020928302919091019091015280612779816159ee565b915050612733565b5050919050565b610104546301000000900460ff166127b25760405162461bcd60e51b8152600401610cc190615bd4565b6127ca600080516020615e5e83398151915233612461565b6127e65760405162461bcd60e51b8152600401610cc190615bfe565b6115b58282613511565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915261010860008360405160200161284791906158fe565b60408051601f19818403018152918152815160209283012083528282019390935290820160002082516101008101845281546001600160801b038116825263ffffffff600160801b8204169382019390935261ffff600160a01b8404169381019390935260ff600160b01b8304811615156060850152600160b81b8304811615156080850152600160c01b83048116151560a0850152600160c81b909204909116151560c0830152600101546001600160a01b031660e082015292915050565b606081831061292957604051631960ccad60e11b815260040160405180910390fd5b606554600090600185101561293d57600194505b80841115612949578093505b600061295487612061565b905084861015612973578585038181101561296d578091505b50612977565b5060005b6000816001600160401b0381111561299157612991614a2d565b6040519080825280602002602001820160405280156129ba578160200160208202803683370190505b509050816000036129d057935061130d92505050565b60006129db88612f06565b9050600081604001516129ec575080515b885b8881141580156129fe5750848714155b15612ab757600081815260696020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff1615159181018290529350612aaf5782516001600160a01b031615612a7057825191505b8a6001600160a01b0316826001600160a01b031603612aaf5780848880600101995081518110612aa257612aa26159d8565b6020026020010181815250505b6001016129ee565b505050928352509095945050505050565b6000612ad481336135fb565b61010454600160381b90046001600160401b031615612b055760405162461bcd60e51b8152600401610cc190615a07565b5061010480546001600160401b03909216600160381b02600160381b600160781b0319909216919091179055565b6000612b3f81336135fb565b610104546301000000900460ff16612b695760405162461bcd60e51b8152600401610cc190615bd4565b60005b828110156112e15760006101096000868685818110612b8d57612b8d6159d8565b90506020020135815260200190815260200160002060006101000a81548160ff0219169083151502179055508080612bc4906159ee565b915050612b6c565b336001600160a01b03831603612bf55760405163b06307db60e01b815260040160405180910390fd5b336000818152606c602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6040805160028082526060828101909352829190816020015b6060815260200190600190039081612c7a57505060408051600280825260608201835292945091906020830190803683370190505090506040518060400160405280600681526020016526a4a72a22a960d11b81525082600081518110612ce357612ce36159d8565b60200260200101819052506040518060400160405280600581526020016420a226a4a760d91b81525082600181518110612d1f57612d1f6159d8565b6020026020010181905250600080516020615e5e83398151915281600081518110612d4c57612d4c6159d8565b6020026020010181815250506000801b81600181518110612d6f57612d6f6159d8565b6020026020010181815250509091565b6000612d8b81336135fb565b600083604051602001612d9e91906158fe565b60408051601f1981840301815291815281516020928301206000908152610107909252902092909255505050565b612dd78484846136e8565b612de9836001600160a01b0316613b34565b8015612dfe5750612dfc84848484613b43565b155b156112e1576040516368d2bf6b60e11b815260040160405180910390fd5b600080612e28836127f0565b90508060600151612e3d576000915050610c99565b806020015163ffffffff16600003612e59576000915050610c99565b600083604051602001612e6c91906158fe565b6040516020818303038152906040528051906020012090508160800151158015612eac5750600081815261010660205260409020612eaa90866134fc565b155b15612ebc57600092505050610c99565b604080830151600083815261010a60209081528382206001600160a01b038a1683529052919091205461ffff90911611612efb57600092505050610c99565b506001949350505050565b612f0e6149c5565b612f166149c5565b6001831080612f2757506065548310155b15612f325792915050565b50600082815260696020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff161580159282019290925290612f925792915050565b61130d836138c0565b6000612fa781336135fb565b6101045460ff16612fca5760405162461bcd60e51b8152600401610cc190615a2c565b81516110639061010b906020850190614941565b6060612fe982613566565b6130295760405162461bcd60e51b81526020600482015260116024820152703737b732bc34b9ba32b73a103a37b5b2b760791b6044820152606401610cc1565b6000613033613c2e565b90508061303f84613c3e565b604051602001613050929190615c2a565b604051602081830303815290604052915050919050565b610104546301000000900460ff166130915760405162461bcd60e51b8152600401610cc190615bd4565b6130a9600080516020615e5e83398151915233612461565b6130c55760405162461bcd60e51b8152600401610cc190615bfe565b60005b83811015611284576131188585838181106130e5576130e56159d8565b90506020020160208101906130fa9190614e2a565b84848481811061310c5761310c6159d8565b90506020020135612788565b80613122816159ee565b9150506130c8565b600081815260d260205260408120610c9990613d3e565b600061314d81336135fb565b610104546301000000900460ff166131775760405162461bcd60e51b8152600401610cc190615bd4565b60005b828110156112e1576001610109600086868581811061319b5761319b6159d8565b90506020020135815260200190815260200160002060006101000a81548160ff02191690831515021790555080806131d2906159ee565b91505061317a565b6131e2613d48565b6131ea613d48565b81516131fd906067906020850190614941565b508051613211906068906020840190614941565b5060016065555050565b61322482611384565b61322e81336135fb565b6110638383613a01565b60005b818110156112e15761326e84848484818110613259576132596159d8565b905060200201602081019061053f9190614e2a565b80613278816159ee565b91505061323b565b6060600061328c613c2e565b90508060405160200161329f9190615c69565b60405160208183030381529060405291505090565b60006132c081336135fb565b6000836040516020016132d391906158fe565b60405160208183030381529060405280519060200120905060005b83518110156112845761333684828151811061330c5761330c6159d8565b60200260200101516101066000858152602001908152602001600020613d7190919063ffffffff16565b5080613341816159ee565b9150506132ee565b600061335581336135fb565b60008360405160200161336891906158fe565b60408051601f198184030181529181528151602092830120600090815261010890925290208054931515600160b01b0260ff60b01b1990941693909317909255505050565b60006001600160e01b03198216635a05180f60e01b1480610c995750610c9982613d86565b8154600160b01b900460ff166134175760405162461bcd60e51b815260206004820152600a6024820152696e6f742061637469766560b01b6044820152606401610cc1565b8154600160801b900463ffffffff168111156134645760405162461bcd60e51b815260206004820152600c60248201526b6f7574206f662073746f636b60a01b6044820152606401610cc1565b6101045462010000900460ff166134b9573233146134b95760405162461bcd60e51b81526020600482015260126024820152711b9bdd08185b1b1bddc818dbdb9d1c9858dd60721b6044820152606401610cc1565b8154819083906010906134da908490600160801b900463ffffffff16615c99565b92506101000a81548163ffffffff021916908363ffffffff1602179055505050565b600061130d836001600160a01b038416613dab565b61010454600160381b90046001600160401b03161561355c5761010454600160381b90046001600160401b03168161354761128b565b6135519190615930565b111561355c57600080fd5b6115b58282613dc3565b60008160011115801561357a575060655482105b8015610c99575050600090815260696020526040902054600160e01b900460ff161590565b6000828152606b602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6136058282612461565b6115b55761361d816001600160a01b03166014613ed4565b613628836020613ed4565b604051602001613639929190615cbe565b60408051601f198184030181529082905262461bcd60e51b8252610cc191600401614b7e565b600061130d836001600160a01b03841661406f565b6000610c99826040517b0ca2ba3432b932bab69029b4b3b732b21026b2b9b9b0b3b29d05199960211b6020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b60008060006136db85856140b9565b91509150611faa81614127565b60006136f3826138c0565b9050836001600160a01b031681600001516001600160a01b03161461372a5760405162a1148160e81b815260040160405180910390fd5b6000336001600160a01b038616148061374857506137488533610baa565b8061376357503361375884610f97565b6001600160a01b0316145b90508061378357604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b0384166137aa57604051633a954ecd60e21b815260040160405180910390fd5b6137b66000848761359f565b6001600160a01b038581166000908152606a6020908152604080832080546001600160401b03198082166001600160401b0392831660001901831617909255898616808652838620805493841693831660019081018416949094179055898652606990945282852080546001600160e01b031916909417600160a01b4290921691909102178355870180845292208054919390911661388957606554821461388957805460208601516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b038a16171781555b50505082846001600160a01b0316866001600160a01b0316600080516020615e7e83398151915260405160405180910390a4611284565b6138c86149c5565b81806001111580156138db575060655481105b156139b957600081815260696020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff161515918101829052906139b75780516001600160a01b03161561394e579392505050565b5060001901600081815260696020908152604091829020825160608101845290546001600160a01b038116808352600160a01b82046001600160401b031693830193909352600160e01b900460ff16151592810192909252156139b2579392505050565b61394e565b505b604051636f96cda160e11b815260040160405180910390fd5b6139dc82826142db565b600082815260d260205260409020611063908261365f565b6060600061130d83614361565b613a0b82826143bd565b600082815260d2602052604090206110639082613d71565b6000818152610109602052604090205460ff1615613a6c5760405162461bcd60e51b8152600401610cc1906020808252600490820152631d5cd95960e21b604082015260600190565b600090815261010960205260409020805460ff19166001179055565b6000613a95828486614424565b949350505050565b6110638363a9059cbb60e01b8484604051602401613abc929190615985565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261443a565b600061130d838361450c565b6000613b0a30613b34565b15905090565b613b18614536565b613b2282826131da565b6115b5613d48565b6115b582826139d2565b6001600160a01b03163b151590565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290613b78903390899088908890600401615d2d565b6020604051808303816000875af1925050508015613bb3575060408051601f3d908101601f19168201909252613bb091810190615d6a565b60015b613c11573d808015613be1576040519150601f19603f3d011682016040523d82523d6000602084013e613be6565b606091505b508051600003613c09576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b606061010b8054610f149061599e565b606081600003613c655750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613c8f5780613c79816159ee565b9150613c889050600a83615a8b565b9150613c69565b6000816001600160401b03811115613ca957613ca9614a2d565b6040519080825280601f01601f191660200182016040528015613cd3576020820181803683370190505b5090505b8415613a9557613ce8600183615d87565b9150613cf5600a86615d9e565b613d00906030615930565b60f81b818381518110613d1557613d156159d8565b60200101906001600160f81b031916908160001a905350613d37600a86615a8b565b9450613cd7565b6000610c99825490565b600054610100900460ff16613d6f5760405162461bcd60e51b8152600401610cc190615db2565b565b600061130d836001600160a01b038416614564565b60006001600160e01b03198216637965db0b60e01b1480610c995750610c9982614657565b60009081526001919091016020526040902054151590565b6065546001600160a01b038316613dec57604051622e076360e81b815260040160405180910390fd5b81600003613e0d5760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b0383166000818152606a6020908152604080832080546001600160801b031981166001600160401b038083168a018116918217600160401b6001600160401b031990941690921783900481168a01811690920217909155858452606990925290912080546001600160e01b031916909217600160a01b4290921691909102179055808083015b6040516001830192906001600160a01b03871690600090600080516020615e7e833981519152908290a4808203613e9a5750606555505050565b60606000613ee3836002615966565b613eee906002615930565b6001600160401b03811115613f0557613f05614a2d565b6040519080825280601f01601f191660200182016040528015613f2f576020820181803683370190505b509050600360fc1b81600081518110613f4a57613f4a6159d8565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110613f7957613f796159d8565b60200101906001600160f81b031916908160001a9053506000613f9d846002615966565b613fa8906001615930565b90505b6001811115614020576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110613fdc57613fdc6159d8565b1a60f81b828281518110613ff257613ff26159d8565b60200101906001600160f81b031916908160001a90535060049490941c9361401981615dfd565b9050613fab565b50831561130d5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610cc1565b600061407b8383613dab565b6140b157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610c99565b506000610c99565b60008082516041036140ef5760208301516040840151606085015160001a6140e3878285856146a7565b94509450505050614120565b8251604003614118576020830151604084015161410d86838361478a565b935093505050614120565b506000905060025b9250929050565b600081600481111561413b5761413b615e14565b036141435750565b600181600481111561415757614157615e14565b0361419f5760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401610cc1565b60028160048111156141b3576141b3615e14565b036142005760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610cc1565b600381600481111561421457614214615e14565b0361426c5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610cc1565b600481600481111561428057614280615e14565b036142d85760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610cc1565b50565b6142e58282612461565b6115b557600082815260a0602090815260408083206001600160a01b03851684529091529020805460ff1916600117905561431d3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156143b157602002820191906000526020600020905b81548152602001906001019080831161439d575b50505050509050919050565b6143c78282612461565b156115b557600082815260a0602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60008261443185846147c3565b14949350505050565b600061448f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661482f9092919063ffffffff16565b80519091501561106357808060200190518101906144ad9190615e2a565b6110635760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610cc1565b6000826000018281548110614523576145236159d8565b9060005260206000200154905092915050565b600054610100900460ff1661455d5760405162461bcd60e51b8152600401610cc190615db2565b6001606e55565b6000818152600183016020526040812054801561464d576000614588600183615d87565b855490915060009061459c90600190615d87565b90508181146146015760008660000182815481106145bc576145bc6159d8565b90600052602060002001549050808760000184815481106145df576145df6159d8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061461257614612615e47565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610c99565b6000915050610c99565b60006001600160e01b031982166380ac58cd60e01b148061468857506001600160e01b03198216635b5e139f60e01b145b80610c9957506301ffc9a760e01b6001600160e01b0319831614610c99565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b038311156146d45750600090506003614781565b8460ff16601b141580156146ec57508460ff16601c14155b156146fd5750600090506004614781565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614751573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661477a57600060019250925050614781565b9150600090505b94509492505050565b6000806001600160ff1b038316816147a760ff86901c601b615930565b90506147b5878288856146a7565b935093505050935093915050565b600081815b8451811015611faa5760008582815181106147e5576147e56159d8565b6020026020010151905080831161480b576000838152602082905260409020925061481c565b600081815260208490526040902092505b5080614827816159ee565b9150506147c8565b6060613a9584846000858561484385613b34565b61488f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610cc1565b600080866001600160a01b031685876040516148ab91906158fe565b60006040518083038185875af1925050503d80600081146148e8576040519150601f19603f3d011682016040523d82523d6000602084013e6148ed565b606091505b50915091506148fd828286614908565b979650505050505050565b6060831561491757508161130d565b8251156149275782518084602001fd5b8160405162461bcd60e51b8152600401610cc19190614b7e565b82805461494d9061599e565b90600052602060002090601f01602090048101928261496f57600085556149b5565b82601f1061498857805160ff19168380011785556149b5565b828001600101855582156149b5579182015b828111156149b557825182559160200191906001019061499a565b506149c19291506149e5565b5090565b604080516060810182526000808252602082018190529181019190915290565b5b808211156149c157600081556001016149e6565b6001600160e01b0319811681146142d857600080fd5b600060208284031215614a2257600080fd5b813561130d816149fa565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614a6b57614a6b614a2d565b604052919050565b600082601f830112614a8457600080fd5b81356001600160401b03811115614a9d57614a9d614a2d565b614ab0601f8201601f1916602001614a43565b818152846020838601011115614ac557600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215614af557600080fd5b82356001600160401b03811115614b0b57600080fd5b614b1785828601614a73565b95602094909401359450505050565b60005b83811015614b41578181015183820152602001614b29565b838111156112e15750506000910152565b60008151808452614b6a816020860160208601614b26565b601f01601f19169290920160200192915050565b60208152600061130d6020830184614b52565b600060208284031215614ba357600080fd5b5035919050565b6001600160a01b0391909116815260200190565b6001600160a01b03811681146142d857600080fd5b60008060408385031215614be657600080fd5b8235614bf181614bbe565b946020939093013593505050565b600082825180855260208086019550808260051b84010181860160005b84811015614c4a57601f19868403018952614c38838351614b52565b98840198925090830190600101614c1c565b5090979650505050505050565b60208152600061130d6020830184614bff565b60006001600160401b03821115614c8357614c83614a2d565b5060051b60200190565b60008060408385031215614ca057600080fd5b82356001600160401b0380821115614cb757600080fd5b614cc386838701614a73565b9350602091508185013581811115614cda57600080fd5b85019050601f81018613614ced57600080fd5b8035614d00614cfb82614c6a565b614a43565b81815260059190911b82018301908381019088831115614d1f57600080fd5b928401925b82841015614d46578335614d3781614bbe565b82529284019290840190614d24565b80955050505050509250929050565b60008083601f840112614d6757600080fd5b5081356001600160401b03811115614d7e57600080fd5b6020830191508360208260051b850101111561412057600080fd5b600080600060408486031215614dae57600080fd5b8335925060208401356001600160401b03811115614dcb57600080fd5b614dd786828701614d55565b9497909650939450505050565b60008060408385031215614df757600080fd5b8235915060208301356001600160401b03811115614e1457600080fd5b614e2085828601614a73565b9150509250929050565b600060208284031215614e3c57600080fd5b813561130d81614bbe565b6020808252825182820181905260009190848201906040850190845b8181101561243d57835183529284019291840191600101614e63565b600080600060608486031215614e9457600080fd5b8335614e9f81614bbe565b92506020840135614eaf81614bbe565b929592945050506040919091013590565b60008060408385031215614ed357600080fd5b823591506020830135614ee581614bbe565b809150509250929050565b600060208284031215614f0257600080fd5b81356001600160401b03811115614f1857600080fd5b613a9584828501614a73565b6020808252825182820181905260009190848201906040850190845b8181101561243d5783516001600160a01b031683529284019291840191600101614f40565b80356001600160801b0381168114614f7c57600080fd5b919050565b803563ffffffff81168114614f7c57600080fd5b803561ffff81168114614f7c57600080fd5b80151581146142d857600080fd5b8035614f7c81614fa7565b600080600080600060a08688031215614fd857600080fd5b85356001600160401b03811115614fee57600080fd5b614ffa88828901614a73565b95505061500960208701614f65565b935061501760408701614f81565b925061502560608701614f95565b9150608086013561503581614fa7565b809150509295509295909350565b600080600080600080600060e0888a03121561505e57600080fd5b873561506981614bbe565b96506020880135955060408801359450606088013593506080880135925060a088013561509581614bbe565b915060c08801356001600160401b038111156150b057600080fd5b6150bc8a828b01614a73565b91505092959891949750929550565b600080600080600080600080610100898b0312156150e857600080fd5b88356001600160401b03808211156150ff57600080fd5b61510b8c838d01614a73565b995060209150818b013561511e81614bbe565b985060408b0135975060608b0135965060808b0135955060a08b0135945060c08b013561514a81614bbe565b935060e08b01358181111561515e57600080fd5b8b019050601f81018c1361517157600080fd5b803561517f614cfb82614c6a565b81815260059190911b8201830190838101908e83111561519e57600080fd5b928401925b828410156151bc578335825292840192908401906151a3565b80955050505050509295985092959890939650565b600080600080600080600080610100898b0312156151ee57600080fd5b88356001600160401b0381111561520457600080fd5b6152108b828c01614a73565b98505061521f60208a01614f65565b965061522d60408a01614f81565b955061523b60608a01614f95565b9450608089013561524b81614fa7565b935060a089013561525b81614fa7565b925060c089013561526b81614fa7565b915060e089013561527b81614bbe565b809150509295985092959890939650565b6000602080838503121561529f57600080fd5b82356001600160401b038111156152b557600080fd5b8301601f810185136152c657600080fd5b80356152d4614cfb82614c6a565b81815260059190911b820183019083810190878311156152f357600080fd5b928401925b828410156148fd578335825292840192908401906152f8565b80516001600160a01b031682526020808201516001600160401b0316908301526040908101511515910152565b6020808252825182820181905260009190848201906040850190845b8181101561243d5761536d838551615311565b928401926060929092019160010161535a565b60008060008060008060c0878903121561539957600080fd5b86356153a481614fa7565b955060208701356153b481614fa7565b945060408701356153c481614fa7565b935060608701356153d481614fa7565b925060808701356153e481614fa7565b915060a08701356153f481614fa7565b809150509295509295509295565b600080600080600080600080610100898b03121561541f57600080fd5b883561542a81614bbe565b97506020890135965060408901359550606089013594506080890135935060a089013561545681614bbe565b925060c089013561546681614bbe565b8092505060e089013590509295985092959890939650565b6000806040838503121561549157600080fd5b50508035926020909101359150565b600080600080606085870312156154b657600080fd5b84356001600160401b03808211156154cd57600080fd5b818701915087601f8301126154e157600080fd5b8135818111156154f057600080fd5b88602082850101111561550257600080fd5b6020928301965094506155189187019050614f65565b9150604085013561552881614bbe565b939692955090935050565b81516001600160801b0316815260208083015163ffffffff169082015260408083015161ffff16908201526060808301511515908201526080828101516101008301916155839084018215159052565b5060a083015161559760a084018215159052565b5060c08301516155ab60c084018215159052565b5060e08301516122a060e08401826001600160a01b03169052565b6000806000606084860312156155db57600080fd5b83356155e681614bbe565b95602085013595506040909401359392505050565b60006020828403121561560d57600080fd5b81356001600160401b038116811461130d57600080fd5b6000806020838503121561563757600080fd5b82356001600160401b0381111561564d57600080fd5b61565985828601614d55565b90969095509350505050565b6000806040838503121561567857600080fd5b823561568381614bbe565b91506020830135614ee581614fa7565b6040815260006156a66040830185614bff565b82810360208481019190915284518083528582019282019060005b81811015614c4a578451835293830193918301916001016156c1565b600080600080608085870312156156f357600080fd5b84356156fe81614bbe565b9350602085013561570e81614bbe565b92506040850135915060608501356001600160401b0381111561573057600080fd5b61573c87828801614a73565b91505092959194509250565b6000806040838503121561575b57600080fd5b823561576681614bbe565b915060208301356001600160401b03811115614e1457600080fd5b60608101610c998284615311565b600080600080604085870312156157a557600080fd5b84356001600160401b03808211156157bc57600080fd5b6157c888838901614d55565b909650945060208701359150808211156157e157600080fd5b506157ee87828801614d55565b95989497509550505050565b6000806040838503121561580d57600080fd5b82356001600160401b038082111561582457600080fd5b61583086838701614a73565b9350602085013591508082111561584657600080fd5b50614e2085828601614a73565b6000806040838503121561586657600080fd5b823561587181614bbe565b91506020830135614ee581614bbe565b6000806040838503121561589457600080fd5b82356001600160401b038111156158aa57600080fd5b6158b685828601614a73565b9250506020830135614ee581614fa7565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60008251615910818460208701614b26565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b600082198211156159435761594361591a565b500190565b6020808252600490820152636e6f706560e01b604082015260600190565b60008160001904831182151516156159805761598061591a565b500290565b6001600160a01b03929092168252602082015260400190565b600181811c908216806159b257607f821691505b6020821081036159d257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b600060018201615a0057615a0061591a565b5060010190565b6020808252600b908201526a185b1c9958591e481cd95d60aa1b604082015260600190565b6020808252600d908201526c6e6f7420617661696c61626c6560981b604082015260600190565b6020808252600890820152677069636b206f6e6560c01b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082615a9a57615a9a615a75565b500490565b600060208284031215615ab157600080fd5b5051919050565b8035614f7c81614bbe565b60008060008060008060008060008060006101608c8e031215615ae557600080fd5b6001600160401b038c35811015615afb57600080fd5b615b088e8e358f01614a73565b9b508060208e01351115615b1b57600080fd5b615b2b8e60208f01358f01614a73565b9a508060408e01351115615b3e57600080fd5b50615b4f8d60408e01358e01614a73565b9850615b5d60608d01615ab8565b9750615b6b60808d01614fb5565b9650615b7960a08d01614fb5565b9550615b8760c08d01614fb5565b9450615b9560e08d01614fb5565b9350615ba46101008d01614fb5565b9250615bb36101208d01614fb5565b9150615bc26101408d01614fb5565b90509295989b509295989b9093969950565b60208082526010908201526f64697361626c6564206665617475726560801b604082015260600190565b6020808252601290820152713932b8bab4b932903832b936b4b9b9b4b7b760711b604082015260600190565b60008351615c3c818460208801614b26565b637572692f60e01b9083019081528351615c5d816004840160208801614b26565b01600401949350505050565b60008251615c7b818460208701614b26565b6b636f6e74726163745f75726960a01b920191825250600c01919050565b600063ffffffff83811690831681811015615cb657615cb661591a565b039392505050565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b815260008351615cf0816017850160208801614b26565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351615d21816028840160208801614b26565b01602801949350505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090615d6090830184614b52565b9695505050505050565b600060208284031215615d7c57600080fd5b815161130d816149fa565b600082821015615d9957615d9961591a565b500390565b600082615dad57615dad615a75565b500690565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600081615e0c57615e0c61591a565b506000190190565b634e487b7160e01b600052602160045260246000fd5b600060208284031215615e3c57600080fd5b815161130d81614fa7565b634e487b7160e01b600052603160045260246000fdfe9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220af6b4159ab96119157615b59739f8944ca587d5daa6e0a73833a9a91306c283764736f6c634300080d0033

Libraries Used


Deployed Bytecode Sourcemap

122257:20065:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;141902:417;;;;;;;;;;-1:-1:-1;141902:417:0;;;;;:::i;:::-;;:::i;:::-;;;661:14:1;;654:22;636:41;;624:2;609:18;141902:417:0;;;;;;;;127784:1264;;;;;;:::i;:::-;;:::i;:::-;;90916:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;92508:245::-;;;;;;;;;;-1:-1:-1;92508:245:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;92079:363::-;;;;;;;;;;-1:-1:-1;92079:363:0;;;;;:::i;:::-;;:::i;123344:26::-;;;;;;;;;;-1:-1:-1;123344:26:0;;;;;:::i;:::-;;:::i;125699:96::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;135058:394::-;;;;;;;;;;-1:-1:-1;135058:394:0;;;;;:::i;:::-;;:::i;86926:303::-;;;;;;;;;;;;;:::i;:::-;;;6148:25:1;;;6136:2;6121:18;86926:303:0;6002:177:1;124354:197:0;;;;;;;;;;-1:-1:-1;124354:197:0;;;;;:::i;:::-;;:::i;132562:223::-;;;;;;;;;;-1:-1:-1;132562:223:0;;;;;:::i;:::-;;:::i;124559:286::-;;;;;;;;;;-1:-1:-1;124559:286:0;;;;;:::i;:::-;;:::i;125528:163::-;;;;;;;;;;-1:-1:-1;125528:163:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;93496:170::-;;;;;;;;;;-1:-1:-1;93496:170:0;;;;;:::i;:::-;;:::i;111491:131::-;;;;;;;;;;-1:-1:-1;111491:131:0;;;;;:::i;:::-;;:::i;78705:1382::-;;;;;;;;;;-1:-1:-1;78705:1382:0;;;;;:::i;:::-;;:::i;111884:147::-;;;;;;;;;;-1:-1:-1;111884:147:0;;;;;:::i;:::-;;:::i;135870:205::-;;;;;;;;;;-1:-1:-1;135870:205:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;112932:218::-;;;;;;;;;;-1:-1:-1;112932:218:0;;;;;:::i;:::-;;:::i;134517:533::-;;;;;;;;;;-1:-1:-1;134517:533:0;;;;;:::i;:::-;;:::i;123779:26::-;;;;;;;;;;-1:-1:-1;123779:26:0;;;;-1:-1:-1;;;;;123779:26:0;;;127265:123;;;;;;;;;;-1:-1:-1;127265:123:0;;;;;:::i;:::-;;:::i;93737:185::-;;;;;;;;;;-1:-1:-1;93737:185:0;;;;;:::i;:::-;;:::i;130418:1025::-;;;;;;:::i;:::-;;:::i;129056:1354::-;;;;;;:::i;:::-;;:::i;140182:790::-;;;;;;;;;;-1:-1:-1;140182:790:0;;;;;:::i;:::-;;:::i;133030:847::-;;;;;;;;;;-1:-1:-1;133030:847:0;;;;;:::i;:::-;;:::i;81317:523::-;;;;;;;;;;-1:-1:-1;81317:523:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;139509:665::-;;;;;;;;;;-1:-1:-1;139509:665:0;;;;;:::i;:::-;;:::i;90724:125::-;;;;;;;;;;-1:-1:-1;90724:125:0;;;;;:::i;:::-;;:::i;88140:206::-;;;;;;;;;;-1:-1:-1;88140:206:0;;;;;:::i;:::-;;:::i;123319:18::-;;;;;;;;;;-1:-1:-1;123319:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;123319:18:0;;;;;-1:-1:-1;;;123319:18:0;;;;;-1:-1:-1;;;123319:18:0;;;;-1:-1:-1;;;123319:18:0;;-1:-1:-1;;;;;123319:18:0;;;;;;;18723:14:1;;18716:22;18698:41;;18782:14;;18775:22;18770:2;18755:18;;18748:50;18841:14;;18834:22;18814:18;;;18807:50;;;;18900:14;;18893:22;18888:2;18873:18;;18866:50;18960:14;18953:22;18947:3;18932:19;;18925:51;19020:14;19013:22;19007:3;18992:19;;18985:51;19080:14;;19073:22;19067:3;19052:19;;19045:51;-1:-1:-1;;;;;19133:31:1;19127:3;19112:19;;19105:60;18685:3;18670:19;123319:18:0;18399:772:1;136687:392:0;;;;;;;;;;-1:-1:-1;136687:392:0;;;;;:::i;:::-;;:::i;131775:642::-;;;;;;;;;;-1:-1:-1;131775:642:0;;;;;:::i;:::-;;:::i;85243:978::-;;;;;;;;;;-1:-1:-1;85243:978:0;;;;;:::i;:::-;;:::i;117032:153::-;;;;;;;;;;-1:-1:-1;117032:153:0;;;;;:::i;:::-;;:::i;110338:147::-;;;;;;;;;;-1:-1:-1;110338:147:0;;;;;:::i;:::-;;:::i;91085:104::-;;;;;;;;;;;;;:::i;137992:1509::-;;;;;;;;;;-1:-1:-1;137992:1509:0;;;;;:::i;:::-;;:::i;125183:337::-;;;;;;;;;;-1:-1:-1;125183:337:0;;;;;:::i;:::-;;:::i;126355:249::-;;;;;;;;;;-1:-1:-1;126355:249:0;;;;;:::i;:::-;;:::i;125803:186::-;;;;;;;;;;-1:-1:-1;125803:186:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;82230:2564::-;;;;;;;;;;-1:-1:-1;82230:2564:0;;;;;:::i;:::-;;:::i;124895:280::-;;;;;;;;;;-1:-1:-1;124895:280:0;;;;;:::i;:::-;;:::i;137457:364::-;;;;;;;;;;-1:-1:-1;137457:364:0;;;;;:::i;:::-;;:::i;109418:49::-;;;;;;;;;;-1:-1:-1;109418:49:0;109463:4;109418:49;;92825:319;;;;;;;;;;-1:-1:-1;92825:319:0;;;;;:::i;:::-;;:::i;123814:329::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;134208:301::-;;;;;;;;;;-1:-1:-1;134208:301:0;;;;;:::i;:::-;;:::i;93993:406::-;;;;;;;;;;-1:-1:-1;93993:406:0;;;;;:::i;:::-;;:::i;136083:596::-;;;;;;;;;;-1:-1:-1;136083:596:0;;;;;:::i;:::-;;:::i;80717:441::-;;;;;;;;;;-1:-1:-1;80717:441:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;126982:275::-;;;;;;;;;;-1:-1:-1;126982:275:0;;;;;:::i;:::-;;:::i;141169:329::-;;;;;;;;;;-1:-1:-1;141169:329:0;;;;;:::i;:::-;;:::i;125997:350::-;;;;;;;;;;-1:-1:-1;125997:350:0;;;;;:::i;:::-;;:::i;117359:142::-;;;;;;;;;;-1:-1:-1;117359:142:0;;;;;:::i;:::-;;:::i;137087:362::-;;;;;;;;;;-1:-1:-1;137087:362:0;;;;;:::i;:::-;;:::i;86229:264::-;;;;;;;;;;-1:-1:-1;86229:264:0;;;;;:::i;:::-;;:::i;122596:62::-;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;122596:62:0;;112276:149;;;;;;;;;;-1:-1:-1;112276:149:0;;;;;:::i;:::-;;:::i;78485:39::-;;;;;;;;;;;;;;;;124151:195;;;;;;;;;;-1:-1:-1;124151:195:0;;;;;:::i;:::-;;:::i;140980:181::-;;;;;;;;;;;;;:::i;93215:214::-;;;;;;;;;;-1:-1:-1;93215:214:0;;;;;:::i;:::-;-1:-1:-1;;;;;93386:25:0;;;93357:4;93386:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;93215:214;135460:402;;;;;;;;;;-1:-1:-1;135460:402:0;;;;;:::i;:::-;;:::i;122665:54::-;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;122665:54:0;;;;;133885:315;;;;;;;;;;-1:-1:-1;133885:315:0;;;;;:::i;:::-;;:::i;141902:417::-;142089:4;-1:-1:-1;;;;;;142131:51:0;;-1:-1:-1;;;142131:51:0;;:127;;-1:-1:-1;;;;;;;142199:59:0;;-1:-1:-1;;;142199:59:0;142131:127;:180;;;;142275:36;142299:11;142275:23;:36::i;:::-;142111:200;141902:417;-1:-1:-1;;141902:417:0:o;127784:1264::-;120201:1;120976:7;;:19;120968:63;;;;-1:-1:-1;;;120968:63:0;;;;;;;:::i;:::-;;;;;;;;;120201:1;121109:7;:18;127934:27:::1;::::0;127910:11:::1;::::0;127934:27:::1;::::0;127951:9;;127934:27:::1;;;:::i;:::-;;::::0;;-1:-1:-1;;127934:27:0;;::::1;::::0;;;;;;127924:38;;127934:27:::1;127924:38:::0;;::::1;::::0;127973:23:::1;127999:14:::0;;;:9:::1;:14:::0;;;;;127924:38;;-1:-1:-1;128026:30:0::1;127999:14:::0;128049:6;128026:11:::1;:30::i;:::-;128373:22:::0;;-1:-1:-1;;;128373:22:0;::::1;;;128372:23;128364:46;;;::::0;-1:-1:-1;;;128364:46:0;;29235:2:1;128364:46:0::1;::::0;::::1;29217:21:1::0;29274:2;29254:18;;;29247:30;-1:-1:-1;;;29293:18:1;;;29286:40;29343:18;;128364:46:0::1;29033:334:1::0;128364:46:0::1;128428:18:::0;;-1:-1:-1;;;128428:18:0;::::1;;;128423:450;;128471:15;::::0;;;:10:::1;:15;::::0;;;;:36:::1;::::0;128496:10:::1;128471:24;:36::i;:::-;128463:45;;;::::0;::::1;;128613:23:::0;;::::1;128549:18:::0;;;:13:::1;:18;::::0;;;;;;;128568:10:::1;128549:30:::0;;;;;;;;-1:-1:-1;;;128613:23:0;;::::1;;;::::0;128549:39:::1;::::0;128582:6;;128549:39:::1;:::i;:::-;:87;;128523:161;;;::::0;-1:-1:-1;;;128523:161:0;;29839:2:1;128523:161:0::1;::::0;::::1;29821:21:1::0;29878:2;29858:18;;;29851:30;-1:-1:-1;;;29897:18:1;;;29890:42;29949:18;;128523:161:0::1;29637:336:1::0;128523:161:0::1;128699:18;::::0;;;:13:::1;:18;::::0;;;;;;;128718:10:::1;128699:30:::0;;;;;;;:40;;128733:6;;128699:18;:40:::1;::::0;128733:6;;128699:40:::1;:::i;:::-;::::0;;;-1:-1:-1;128423:450:0::1;::::0;-1:-1:-1;128423:450:0::1;;128790:23:::0;;-1:-1:-1;;;128790:23:0;::::1;;;128780:33:::0;::::1;;128772:50;;;;-1:-1:-1::0;;;128772:50:0::1;;;;;;;:::i;:::-;128926:22;::::0;::::1;::::0;128963:15;;128885:11:::1;::::0;:26:::1;::::0;-1:-1:-1;;;;;128926:22:0;;::::1;::::0;128963:24:::1;::::0;128981:6;;-1:-1:-1;;;;;128963:15:0::1;:24;:::i;:::-;128885:113;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;129011:29;129021:10;129033:6;129011:9;:29::i;:::-;-1:-1:-1::0;;120157:1:0;121288:7;:22;-1:-1:-1;;127784:1264:0:o;90916:100::-;90970:13;91003:5;90996:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90916:100;:::o;92508:245::-;92612:7;92642:16;92650:7;92642;:16::i;:::-;92637:64;;92667:34;;-1:-1:-1;;;92667:34:0;;;;;;;;;;;92637:64;-1:-1:-1;92721:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;92721:24:0;;92508:245::o;92079:363::-;92152:13;92168:16;92176:7;92168;:16::i;:::-;92152:32;;92205:5;-1:-1:-1;;;;;92199:11:0;:2;-1:-1:-1;;;;;92199:11:0;;92195:48;;92219:24;;-1:-1:-1;;;92219:24:0;;;;;;;;;;;92195:48;74235:10;-1:-1:-1;;;;;92260:21:0;;;;;;:63;;-1:-1:-1;92286:37:0;92303:5;74235:10;93215:214;:::i;92286:37::-;92285:38;92260:63;92256:138;;;92347:35;;-1:-1:-1;;;92347:35:0;;;;;;;;;;;92256:138;92406:28;92415:2;92419:7;92428:5;92406:8;:28::i;:::-;92141:301;92079:363;;:::o;123344:26::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;125699:96::-;125742:15;125777:10;125770:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;125699:96;:::o;135058:394::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;135279:11:::1;135320:9;135303:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;135293:38;;;;;;135279:52;;135347:9;135342:103;135366:7;:14;135362:1;:18;135342:103;;;135402:31;135422:7;135430:1;135422:10;;;;;;;;:::i;:::-;;;;;;;135402;:15;135413:3;135402:15;;;;;;;;;;;:19;;:31;;;;:::i;:::-;-1:-1:-1::0;135382:3:0;::::1;::::0;::::1;:::i;:::-;;;;135342:103;;;;135192:260;135058:394:::0;;;:::o;86926:303::-;87180:12;;87164:13;;:28;-1:-1:-1;;87164:46:0;;86926:303::o;124354:197::-;124441:9;124436:108;124456:19;;;124436:108;;;124497:35;124514:4;124520:8;;124529:1;124520:11;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;124497:35::-;124477:3;;;;:::i;:::-;;;;124436:108;;;;124354:197;;;:::o;132562:223::-;132668:4;132710:67;-1:-1:-1;;;;;;;;;;;132731:45:0;132745:19;132759:4;132745:13;:19::i;:::-;132766:9;132731:13;:45::i;132710:67::-;132690:87;132562:223;-1:-1:-1;;;132562:223:0:o;124559:286::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;124683:11:::1;::::0;-1:-1:-1;;;;;124683:11:0::1;:25:::0;124675:49:::1;;;;-1:-1:-1::0;;;124675:49:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;124811:11:0::1;:26:::0;;-1:-1:-1;;;;;;124811:26:0::1;-1:-1:-1::0;;;;;124811:26:0;;;::::1;::::0;;;::::1;::::0;;124559:286::o;125528:163::-;125611:26;125662:21;125676:6;125662:13;:21::i;93496:170::-;93630:28;93640:4;93646:2;93650:7;93630:9;:28::i;111491:131::-;111565:7;111592:12;;;:6;:12;;;;;:22;;;;111491:131::o;78705:1382::-;78772:8;78784:1;78772:13;78768:49;;78794:23;;-1:-1:-1;;;78794:23:0;;;;;;;;;;;78768:49;86673:1;78832:13;;:32;78828:64;;78873:19;;-1:-1:-1;;;78873:19:0;;;;;;;;;;;78828:64;78939:24;;78903:33;78978:30;;;78974:106;;-1:-1:-1;86673:1:0;78974:106;79123:13;;79094:25;:42;79090:94;;79158:26;;-1:-1:-1;;;79158:26:0;;;;;;;;;;;79090:94;79486:13;;79349:36;;;-1:-1:-1;;79349:40:0;;;-1:-1:-1;79467:97:0;;;-1:-1:-1;79531:13:0;;-1:-1:-1;;79531:17:0;79467:97;79597:25;79580:433;79629:8;79624:1;:13;79580:433;;79720:1;79689:14;;;:11;:14;;;;;:19;-1:-1:-1;;;;;79689:19:0;:33;:59;;;;-1:-1:-1;79727:14:0;;;;:11;:14;;;;;:21;-1:-1:-1;;;79727:21:0;;;;79726:22;79689:59;79663:335;;;79791:31;79825:15;79838:1;79825:12;:15::i;:::-;79885:14;;;79863;;;:11;:14;;;;;;;;:36;;79954:24;;;;;-1:-1:-1;;;;;79922:56:0;-1:-1:-1;;;79922:56:0;-1:-1:-1;;;;;;79922:56:0;;;-1:-1:-1;;;;;79863:36:0;;;79922:56;;;;;;;-1:-1:-1;79663:335:0;79639:3;;79580:433;;;-1:-1:-1;80067:1:0;80056:12;80029:24;:39;-1:-1:-1;;78705:1382:0:o;111884:147::-;111967:18;111980:4;111967:12;:18::i;:::-;109909:30;109920:4;74235:10;109909;:30::i;:::-;111998:25:::1;112009:4;112015:7;111998:10;:25::i;135870:205::-:0;135967:16;136008:59;:10;:50;136046:9;136029:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;136019:38;;;;;;136008:50;;;;;;;;;;;:57;:59::i;112932:218::-;-1:-1:-1;;;;;113028:23:0;;74235:10;113028:23;113020:83;;;;-1:-1:-1;;;113020:83:0;;31969:2:1;113020:83:0;;;31951:21:1;32008:2;31988:18;;;31981:30;32047:34;32027:18;;;32020:62;-1:-1:-1;;;32098:18:1;;;32091:45;32153:19;;113020:83:0;31767:411:1;113020:83:0;113116:26;113128:4;113134:7;113116:11;:26::i;:::-;112932:218;;:::o;134517:533::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;134808:11:::1;134849:9;134832:27;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;134832:27:0;;::::1;::::0;;;;;;134822:38;;134832:27:::1;134822:38:::0;;::::1;::::0;134871:14:::1;::::0;;;:9:::1;:14:::0;;;;;:29;;135007:35;::::1;;-1:-1:-1::0;;;135007:35:0::1;-1:-1:-1::0;;;;134951:45:0::1;::::0;;::::1;-1:-1:-1::0;;;134951:45:0::1;135007:35:::0;;;;-1:-1:-1;;;;134911:29:0::1;::::0;;::::1;-1:-1:-1::0;;;134911:29:0::1;-1:-1:-1::0;;;;;;134911:29:0;;;-1:-1:-1;;;;;134871:29:0;;::::1;134911::::0;;;;;;;::::1;135007:35:::0;;;;;;;;;;;::::1;::::0;;-1:-1:-1;;;134517:533:0:o;127265:123::-;127346:34;;-1:-1:-1;;;127346:34:0;;32385:2:1;127346:34:0;;;32367:21:1;32424:2;32404:18;;;32397:30;-1:-1:-1;;;32443:18:1;;;32436:54;32507:18;;127346:34:0;32183:348:1;93737:185:0;93875:39;93892:4;93898:2;93902:7;93875:39;;;;;;;;;;;;:16;:39::i;130418:1025::-;130664:12;130679:213;130698:6;130719;130740:7;130762:5;130782:12;130809:16;130848:4;130868:13;130679:4;:213::i;:::-;130911:6;:20;130664:228;;-1:-1:-1;;;;130911:20:0;;;;130903:46;;;;-1:-1:-1;;;130903:46:0;;;;;;;:::i;:::-;130968:6;:21;;;;;;130960:47;;;;-1:-1:-1;;;130960:47:0;;;;;;;:::i;:::-;131028:27;131039:4;131045:9;131028:10;:27::i;:::-;131020:36;;;;;;131069:16;131079:5;131069:9;:16::i;:::-;-1:-1:-1;;;;;131100:20:0;;;131096:90;;-1:-1:-1;;;;;131145:20:0;;131155:10;131145:20;131137:37;;;;-1:-1:-1;;;131137:37:0;;;;;;;:::i;:::-;131215:1;131206:6;:10;131198:31;;;;-1:-1:-1;;;131198:31:0;;;;;;;:::i;:::-;131273:12;;131265:29;;;;-1:-1:-1;;;131265:29:0;;;;;;;:::i;:::-;131332:11;:26;131359:16;131377:21;131392:6;131377:12;:21;:::i;:::-;131332:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;131410:25;131420:6;131428;131410:9;:25::i;:::-;130653:790;130418:1025;;;;;;;:::o;129056:1354::-;129336:11;129377:9;129360:27;;;;;;;;:::i;:::-;;;;-1:-1:-1;;129360:27:0;;;;;;;;;129350:38;;129360:27;129350:38;;;;129399:23;129425:14;;;:9;:14;;;;;129350:38;;-1:-1:-1;129452:30:0;129425:14;129475:6;129452:11;:30::i;:::-;129671:22;;-1:-1:-1;;;129671:22:0;;;;129663:42;;;;-1:-1:-1;;;129663:42:0;;33416:2:1;129663:42:0;;;33398:21:1;33455:1;33435:18;;;33428:29;-1:-1:-1;;;33473:18:1;;;33466:37;33520:18;;129663:42:0;33214:330:1;129663:42:0;129718:12;129733:213;129752:6;129773;129794:7;129816:5;129836:12;129863:16;129902:4;129922:13;129733:4;:213::i;:::-;129984:15;;;;:10;:15;;;;;;129718:228;;-1:-1:-1;129965:42:0;;129718:228;;130001:5;129965:12;:42::i;:::-;129957:66;;;;-1:-1:-1;;;129957:66:0;;33751:2:1;129957:66:0;;;33733:21:1;33790:2;33770:18;;;33763:30;-1:-1:-1;;;33809:18:1;;;33802:41;33860:18;;129957:66:0;33549:335:1;129957:66:0;130036:16;130046:5;130036:9;:16::i;:::-;-1:-1:-1;;;;;130067:20:0;;;130063:90;;-1:-1:-1;;;;;130112:20:0;;130122:10;130112:20;130104:37;;;;-1:-1:-1;;;130104:37:0;;;;;;;:::i;:::-;130182:1;130173:6;:10;130165:31;;;;-1:-1:-1;;;130165:31:0;;;;;;;:::i;:::-;130240:12;;130232:29;;;;-1:-1:-1;;;130232:29:0;;;;;;;:::i;:::-;130299:11;:26;130326:16;130344:21;130359:6;130344:12;:21;:::i;:::-;130299:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130377:25;130387:6;130395;130377:9;:25::i;:::-;129325:1085;;;129056:1354;;;;;;;;:::o;140182:790::-;120201:1;120976:7;;:19;120968:63;;;;-1:-1:-1;;;120968:63:0;;;;;;;:::i;:::-;120201:1;121109:7;:18;140271:11:::1;::::0;-1:-1:-1;;;;;140271:11:0::1;::::0;140293:155:::1;;140347:39;109463:4;140375:10;140347:7;:39::i;:::-;140339:62;;;::::0;-1:-1:-1;;;140339:62:0;;34091:2:1;140339:62:0::1;::::0;::::1;34073:21:1::0;34130:2;34110:18;;;34103:30;-1:-1:-1;;;34149:18:1;;;34142:40;34199:18;;140339:62:0::1;33889:334:1::0;140339:62:0::1;-1:-1:-1::0;140426:10:0::1;140293:155;-1:-1:-1::0;;;;;140462:26:0;::::1;140458:507;;140513:11;::::0;140578:3:::1;::::0;-1:-1:-1;;;;;140513:11:0;;::::1;::::0;140505:100:::1;::::0;140585:5:::1;::::0;140554:27:::1;::::0;:21:::1;:27;:::i;:::-;140553:37;;;;:::i;:::-;140505:100;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;::::1;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;140620:48:0::1;::::0;-1:-1:-1;;;;;140620:25:0;::::1;::::0;140646:21:::1;140620:48:::0;::::1;;;::::0;::::1;::::0;;;140646:21;140620:25;:48;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;140458:507;;;140788:11;::::0;140852:3:::1;::::0;140819:30:::1;::::0;-1:-1:-1;;;140819:30:0;;140723:12;;140751:128:::1;::::0;-1:-1:-1;;;;;140788:11:0;;::::1;::::0;140859:5:::1;::::0;140819:15;::::1;::::0;::::1;::::0;:30:::1;::::0;140843:4:::1;::::0;140819:30:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:36;;;;:::i;:::-;140818:46;;;;:::i;:::-;-1:-1:-1::0;;;;;140751:18:0;::::1;::::0;:128;:18:::1;:128::i;:::-;140894:59;140913:7;140922:5;-1:-1:-1::0;;;;;140922:15:0::1;;140946:4;140922:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;140894:59::-;140686:279;140458:507;-1:-1:-1::0;;120157:1:0;121288:7;:22;140182:790::o;133030:847::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;133400:11:::1;133441:9;133424:27;;;;;;;;:::i;:::-;;::::0;;;;::::1;-1:-1:-1::0;;133424:27:0;;;;;;133414:38;;133424:27:::1;133414:38:::0;;::::1;::::0;133474:14:::1;::::0;;;:9:::1;:14:::0;;;;;:20;133414:38;;-1:-1:-1;;;;133474:20:0;::::1;;;133473:21;133465:47;;;::::0;-1:-1:-1;;;133465:47:0;;34876:2:1;133465:47:0::1;::::0;::::1;34858:21:1::0;34915:2;34895:18;;;34888:30;-1:-1:-1;;;34934:18:1;;;34927:43;34987:18;;133465:47:0::1;34674:337:1::0;133465:47:0::1;133523:10;:26:::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;133523:26:0;;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;;133577:292;;;;;;;;133605:6;-1:-1:-1::0;;;;;133577:292:0::1;;;;;133633:6;133577:292;;;;;;133669:14;133577:292;;;;;;133708:9;133577:292;;;;;;133742:9;133577:292;;;;;;133780:9;133577:292;;;;;;133853:4;133577:292;;;;;;133818:13;-1:-1:-1::0;;;;;133577:292:0::1;;;::::0;133560:9:::1;:14;133570:3;133560:14;;;;;;;;;;;:309;;;;;;;;;;;;;-1:-1:-1::0;;;;;133560:309:0::1;;;;;-1:-1:-1::0;;;;;133560:309:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;133560:309:0::1;;;;;-1:-1:-1::0;;;;;133560:309:0::1;;;;;;;;;133313:564;133030:847:::0;;;;;;;;;:::o;81317:523::-;81515:15;;81424:23;;81490:22;81515:15;-1:-1:-1;;;;;81582:68:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;81545:105;;81670:9;81665:125;81686:14;81681:1;:19;81665:125;;81742:32;81762:8;81771:1;81762:11;;;;;;;;:::i;:::-;;;;;;;81742:19;:32::i;:::-;81726:10;81737:1;81726:13;;;;;;;;:::i;:::-;;;;;;;;;;:48;81702:3;;81665:125;;;-1:-1:-1;81811:10:0;81317:523;-1:-1:-1;;;81317:523:0:o;139509:665::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;139775:6:::1;:22:::0;::::1;::::0;::::1;;;139767:31;;;::::0;::::1;;-1:-1:-1::0;139885:6:0::1;:39:::0;;-1:-1:-1;;139935:41:0;139885:39;::::1;;-1:-1:-1::0;;139935:41:0;;;;;139885:39:::1;139935:41:::0;::::1;;::::0;;;::::1;::::0;;;::::1;-1:-1:-1::0;;140035:39:0;139987:37;;::::1;;::::0;;;::::1;-1:-1:-1::0;;140035:39:0;;;;;;;::::1;;::::0;;;::::1;;-1:-1:-1::0;;;;140129:37:0;-1:-1:-1;;;140085:33:0;::::1;;::::0;;;::::1;-1:-1:-1::0;;;;140129:37:0;;-1:-1:-1;;;140129:37:0;::::1;;::::0;;;::::1;;::::0;;139509:665::o;90724:125::-;90788:7;90815:21;90828:7;90815:12;:21::i;:::-;:26;;90724:125;-1:-1:-1;;90724:125:0:o;88140:206::-;88204:7;-1:-1:-1;;;;;88228:19:0;;88224:60;;88256:28;;-1:-1:-1;;;88256:28:0;;;;;;;;;;;88224:60;-1:-1:-1;;;;;;88310:19:0;;;;;:12;:19;;;;;:27;-1:-1:-1;;;;;88310:27:0;;88140:206::o;136687:392::-;136849:10;:17;136779:15;;136812:21;;-1:-1:-1;;;;;136836:31:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136812:55;;136883:9;136878:171;136902:10;:17;136898:21;;136878:171;;;136945:32;136955:6;136963:10;136974:1;136963:13;;;;;;;;:::i;:::-;;;;;;;;136945:32;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:9;:32::i;:::-;136941:97;;;137009:10;137020:1;137009:13;;;;;;;;:::i;:::-;;;;;;;;136998:24;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:5;137004:1;136998:8;;;;;;;;:::i;:::-;;;;;;:24;;;;136941:97;136921:3;;;;:::i;:::-;;;;136878:171;;;-1:-1:-1;137066:5:0;136687:392;-1:-1:-1;;136687:392:0:o;131775:642::-;132106:288;;-1:-1:-1;;;;;;35363:2:1;35399:15;;;35395:24;;132106:288:0;;;35383:37:1;35436:12;;;35429:28;;;35473:12;;;35466:28;;;35510:12;;;35503:28;;;35547:13;;;35540:29;;;35604:15;;;35600:24;;35585:13;;;35578:47;35660:15;;;35656:24;35641:13;;;35634:47;35697:13;;;35690:29;;;132038:7:0;;35735:13:1;;132106:288:0;;;;;;;;;;;;132078:331;;;;;;132058:351;;131775:642;;;;;;;;;;:::o;85243:978::-;85329:16;85388:19;85422:25;85462:22;85487:16;85497:5;85487:9;:16::i;:::-;85462:41;;85518:25;85560:14;-1:-1:-1;;;;;85546:29:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85546:29:0;;85518:57;;85590:31;;:::i;:::-;86673:1;85636:537;85720:14;85705:11;:29;85636:537;;85803:14;;;;:11;:14;;;;;;;;;85791:26;;;;;;;;;-1:-1:-1;;;;;85791:26:0;;;;-1:-1:-1;;;85791:26:0;;-1:-1:-1;;;;;85791:26:0;;;;;;;;-1:-1:-1;;;85791:26:0;;;;;;;;;;;;;;-1:-1:-1;85881:8:0;85836:73;85931:14;;-1:-1:-1;;;;;85931:28:0;;85927:111;;86004:14;;;-1:-1:-1;85927:111:0;86081:5;-1:-1:-1;;;;;86060:26:0;:17;-1:-1:-1;;;;;86060:26:0;;86056:102;;86137:1;86111:8;86120:13;;;;;;86111:23;;;;;;;;:::i;:::-;;;;;;:27;;;;;86056:102;85753:3;;85636:537;;;-1:-1:-1;86194:8:0;;85243:978;-1:-1:-1;;;;;;85243:978:0:o;117032:153::-;117122:7;117149:18;;;:12;:18;;;;;:28;;117171:5;117149:21;:28::i;110338:147::-;110424:4;110448:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;110448:29:0;;;;;;;;;;;;;;;110338:147::o;91085:104::-;91141:13;91174:7;91167:14;;;;;:::i;137992:1509::-;70913:13;;;;;;;:48;;70949:12;;;;70948:13;70913:48;;;70929:16;:14;:16::i;:::-;70905:107;;;;-1:-1:-1;;;70905:107:0;;35961:2:1;70905:107:0;;;35943:21:1;36000:2;35980:18;;;35973:30;36039:34;36019:18;;;36012:62;-1:-1:-1;;;36090:18:1;;;36083:44;36144:19;;70905:107:0;35759:410:1;70905:107:0;71025:19;71048:13;;;;;;71047:14;71072:101;;;;71107:13;:20;;-1:-1:-1;;71142:19:0;;;;;71072:101;138150:12:::1;138136:11;;:26;;;;;-1:-1:-1::0;;;;;138136:26:0::1;;;;;-1:-1:-1::0;;;;;138136:26:0::1;;;;;;138179:4;-1:-1:-1::0;;;;;138173:10:0::1;:3;:10;;;;138211:18;138244:20:::0;138279:26:::1;138320:13:::0;138348:20:::1;138383:21:::0;138419:19:::1;138453:20:::0;138488:22:::1;138525:17:::0;138557:19:::1;138619:7;;138590:395;;;;;;;:::i;:::-;138196:789;;;;;;;;;;;;;;;;;;;;;;138998:24;139009:4;139015:6;138998:10;:24::i;:::-;139033:37;109463:4;139064:5:::0;139033:10:::1;:37::i;:::-;139083:28:::0;;::::1;::::0;:13:::1;::::0;:28:::1;::::0;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;139131:362:0::1;::::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;;::::1;;;::::0;::::1;::::0;;;;::::1;;::::0;;;;;;;::::1;;::::0;;;;;;;::::1;;::::0;;;;;;;::::1;;::::0;;;;;;;::::1;;::::0;;;;;;-1:-1:-1;139131:362:0;;;;;;;;139122:6:::1;:371:::0;;-1:-1:-1;;139122:371:0;-1:-1:-1;;139122:371:0;;;;;;;;;;::::1;::::0;;;::::1;-1:-1:-1::0;;139122:371:0;;;;::::1;-1:-1:-1::0;;139122:371:0;;;;;;;;::::1;;-1:-1:-1::0;;;;139122:371:0;-1:-1:-1;;;139122:371:0;;::::1;-1:-1:-1::0;;;;139122:371:0;;;;;-1:-1:-1;;;139122:371:0;;::::1;;-1:-1:-1::0;;;;;;;;139122:371:0;-1:-1:-1;;;139122:371:0;;::::1;-1:-1:-1::0;;;;;;;;139122:371:0;;;;;;;-1:-1:-1;;71199:68:0;;;-1:-1:-1;71199:68:0;;-1:-1:-1;71199:68:0;71250:5;71234:21;;-1:-1:-1;;71234:21:0;;;70620:654;137992:1509;;;;:::o;125183:337::-;125269:28;125315:13;125331:24;125350:4;125331:18;:24::i;:::-;125315:40;;125394:5;-1:-1:-1;;;;;125380:20:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;125380:20:0;;125366:34;;125416:9;125411:102;125435:5;125431:1;:9;125411:102;;;125479:22;125493:4;125499:1;125479:13;:22::i;:::-;125462:11;125474:1;125462:14;;;;;;;;:::i;:::-;-1:-1:-1;;;;;125462:39:0;;;:14;;;;;;;;;;;:39;125442:3;;;;:::i;:::-;;;;125411:102;;;;125304:216;125183:337;;;:::o;126355:249::-;126442:6;:21;;;;;;126434:50;;;;-1:-1:-1;;;126434:50:0;;;;;;;:::i;:::-;126503:32;-1:-1:-1;;;;;;;;;;;126524:10:0;126503:7;:32::i;:::-;126495:63;;;;-1:-1:-1;;;126495:63:0;;;;;;;:::i;:::-;126569:27;126579:8;126589:6;126569:9;:27::i;125803:186::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;125932:9:0;:49;125969:9;125952:27;;;;;;;;:::i;:::-;;;;-1:-1:-1;;125952:27:0;;;;;;;;;125942:38;;125952:27;125942:38;;;;125932:49;;;;;;;;;;;;-1:-1:-1;125932:49:0;125925:56;;;;;;;;;-1:-1:-1;;;;;125925:56:0;;;;;-1:-1:-1;;;125925:56:0;;;;;;;;;;;-1:-1:-1;;;125925:56:0;;;;;;;;;;;-1:-1:-1;;;125925:56:0;;;;;;;;;;-1:-1:-1;;;125925:56:0;;;;;;;;;;-1:-1:-1;;;125925:56:0;;;;;;;;;;-1:-1:-1;;;125925:56:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;125925:56:0;;;;;;125803:186;-1:-1:-1;;125803:186:0:o;82230:2564::-;82356:16;82423:4;82414:5;:13;82410:45;;82436:19;;-1:-1:-1;;;82436:19:0;;;;;;;;;;;82410:45;82524:13;;82470:19;;86673:1;82615:5;:23;82611:87;;;86673:1;82659:23;;82611:87;82778:9;82771:4;:16;82767:73;;;82815:9;82808:16;;82767:73;82854:25;82882:16;82892:5;82882:9;:16::i;:::-;82854:44;;83076:4;83068:5;:12;83064:278;;;83123:12;;;83158:31;;;83154:111;;;83234:11;83214:31;;83154:111;83082:198;83064:278;;;-1:-1:-1;83325:1:0;83064:278;83356:25;83398:17;-1:-1:-1;;;;;83384:32:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;83384:32:0;;83356:60;;83435:17;83456:1;83435:22;83431:78;;83485:8;-1:-1:-1;83478:15:0;;-1:-1:-1;;;83478:15:0;83431:78;83653:31;83687:26;83707:5;83687:19;:26::i;:::-;83653:60;;83728:25;83973:9;:16;;;83968:92;;-1:-1:-1;84030:14:0;;83968:92;84109:5;84074:543;84138:4;84133:1;:9;;:45;;;;;84161:17;84146:11;:32;;84133:45;84074:543;;;84247:14;;;;:11;:14;;;;;;;;;84235:26;;;;;;;;;-1:-1:-1;;;;;84235:26:0;;;;-1:-1:-1;;;84235:26:0;;-1:-1:-1;;;;;84235:26:0;;;;;;;;-1:-1:-1;;;84235:26:0;;;;;;;;;;;;;;-1:-1:-1;84325:8:0;84280:73;84375:14;;-1:-1:-1;;;;;84375:28:0;;84371:111;;84448:14;;;-1:-1:-1;84371:111:0;84525:5;-1:-1:-1;;;;;84504:26:0;:17;-1:-1:-1;;;;;84504:26:0;;84500:102;;84581:1;84555:8;84564:13;;;;;;84555:23;;;;;;;;:::i;:::-;;;;;;:27;;;;;84500:102;84197:3;;84074:543;;;-1:-1:-1;;;84702:29:0;;;-1:-1:-1;84702:29:0;;82230:2564;-1:-1:-1;;;;;82230:2564:0:o;124895:280::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;125014:6:::1;:16:::0;-1:-1:-1;;;125014:16:0;::::1;-1:-1:-1::0;;;;;125014:16:0::1;:21:::0;125006:45:::1;;;;-1:-1:-1::0;;;125006:45:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;125138:6:0::1;:29:::0;;-1:-1:-1;;;;;125138:29:0;;::::1;-1:-1:-1::0;;;125138:29:0::1;-1:-1:-1::0;;;;;;;;125138:29:0;;::::1;::::0;;;::::1;::::0;;124895:280::o;137457:364::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;137660:6:::1;:21:::0;;;::::1;;;137652:50;;;;-1:-1:-1::0;;;137652:50:0::1;;;;;;;:::i;:::-;137720:9;137715:99;137735:17:::0;;::::1;137715:99;;;137797:5;137774:9;:20;137784:6;;137791:1;137784:9;;;;;;;:::i;:::-;;;;;;;137774:20;;;;;;;;;;;;:28;;;;;;;;;;;;;;;;;;137754:3;;;;;:::i;:::-;;;;137715:99;;92825:319:::0;74235:10;-1:-1:-1;;;;;92956:24:0;;;92952:54;;92989:17;;-1:-1:-1;;;92989:17:0;;;;;;;;;;;92952:54;74235:10;93019:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;93019:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;93019:53:0;;;;;;;;;;93088:48;;636:41:1;;;93019:42:0;;74235:10;93088:48;;609:18:1;93088:48:0;;;;;;;92825:319;;:::o;123814:329::-;123952:15;;;123965:1;123952:15;;;123882:21;123952:15;;;;;;123882:21;;123952:15;;;;;;;;;;;;;;;;;;-1:-1:-1;;123985:16:0;;;123999:1;123985:16;;;;;;;;123944:23;;-1:-1:-1;123985:16:0;123999:1;123985:16;;;;;;;;;;-1:-1:-1;123985:16:0;123978:23;;124014:19;;;;;;;;;;;;;-1:-1:-1;;;124014:19:0;;;:5;124020:1;124014:8;;;;;;;;:::i;:::-;;;;;;:19;;;;124044:18;;;;;;;;;;;;;-1:-1:-1;;;124044:18:0;;;:5;124050:1;124044:8;;;;;;;;:::i;:::-;;;;;;:18;;;;-1:-1:-1;;;;;;;;;;;124075:4:0;124080:1;124075:7;;;;;;;;:::i;:::-;;;;;;:21;;;;;109463:4;124117:18;;124107:4;124112:1;124107:7;;;;;;;;:::i;:::-;;;;;;:28;;;;;123814:329;;:::o;134208:301::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;134416:11:::1;134457:9;134440:27;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;134440:27:0;;::::1;::::0;;;;;;134430:38;;134440:27:::1;134430:38:::0;;::::1;::::0;134479:15:::1;::::0;;;:10:::1;:15:::0;;;;;:22;;;;-1:-1:-1;;;134208:301:0:o;93993:406::-;94160:28;94170:4;94176:2;94180:7;94160:9;:28::i;:::-;94217:15;:2;-1:-1:-1;;;;;94217:13:0;;:15::i;:::-;:89;;;;;94250:56;94281:4;94287:2;94291:7;94300:5;94250:30;:56::i;:::-;94249:57;94217:89;94199:193;;;94340:40;;-1:-1:-1;;;94340:40:0;;;;;;;;;;;136083:596;136191:4;136213:14;136230:20;136240:9;136230;:20::i;:::-;136213:37;;136266:1;:10;;;136261:56;;136300:5;136293:12;;;;;136261:56;136331:1;:7;;;:12;;136342:1;136331:12;136327:57;;136367:5;136360:12;;;;;136327:57;136394:11;136435:9;136418:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;136408:38;;;;;;136394:52;;136462:1;:10;;;136461:11;:48;;;;-1:-1:-1;136477:15:0;;;;:10;:15;;;;;:32;;136502:6;136477:24;:32::i;:::-;136476:33;136461:48;136457:93;;;136533:5;136526:12;;;;;;136457:93;136594:15;;;;;136564:18;;;;:13;:18;;;;;;;-1:-1:-1;;;;;136564:26:0;;;;;;;;;;;:45;;;;-1:-1:-1;136560:90:0;;136633:5;136626:12;;;;;;136560:90;-1:-1:-1;136667:4:0;;136083:596;-1:-1:-1;;;;136083:596:0:o;80717:441::-;80811:21;;:::i;:::-;80850:31;;:::i;:::-;86673:1;80896:7;:25;:53;;;;80936:13;;80925:7;:24;;80896:53;80892:102;;;80973:9;80717:441;-1:-1:-1;;80717:441:0:o;80892:102::-;-1:-1:-1;81016:20:0;;;;:11;:20;;;;;;;;;81004:32;;;;;;;;;-1:-1:-1;;;;;81004:32:0;;;;-1:-1:-1;;;81004:32:0;;-1:-1:-1;;;;;81004:32:0;;;;;;;;-1:-1:-1;;;81004:32:0;;;;;;;;;;;;;;;;81047:65;;81091:9;80717:441;-1:-1:-1;;80717:441:0:o;81047:65::-;81129:21;81142:7;81129:12;:21::i;126982:275::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;127177:6:::1;:21:::0;::::1;;127169:47;;;;-1:-1:-1::0;;;127169:47:0::1;;;;;;;:::i;:::-;127227:22:::0;;::::1;::::0;:13:::1;::::0;:22:::1;::::0;::::1;::::0;::::1;:::i;141169:329::-:0;141287:13;141326:16;141334:7;141326;:16::i;:::-;141318:46;;;;-1:-1:-1;;;141318:46:0;;38509:2:1;141318:46:0;;;38491:21:1;38548:2;38528:18;;;38521:30;-1:-1:-1;;;38567:18:1;;;38560:47;38624:18;;141318:46:0;38307:341:1;141318:46:0;141377:21;141401:10;:8;:10::i;:::-;141377:34;;141453:7;141470:18;:7;:16;:18::i;:::-;141436:53;;;;;;;;;:::i;:::-;;;;;;;;;;;;;141422:68;;;141169:329;;;:::o;125997:350::-;126110:6;:21;;;;;;126102:50;;;;-1:-1:-1;;;126102:50:0;;;;;;;:::i;:::-;126171:32;-1:-1:-1;;;;;;;;;;;126192:10:0;126171:7;:32::i;:::-;126163:63;;;;-1:-1:-1;;;126163:63:0;;;;;;;:::i;:::-;126242:9;126237:103;126257:18;;;126237:103;;;126297:31;126306:7;;126314:1;126306:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;126318:6;;126325:1;126318:9;;;;;;;:::i;:::-;;;;;;;126297:8;:31::i;:::-;126277:3;;;;:::i;:::-;;;;126237:103;;117359:142;117439:7;117466:18;;;:12;:18;;;;;:27;;:25;:27::i;137087:362::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;137289:6:::1;:21:::0;;;::::1;;;137281:50;;;;-1:-1:-1::0;;;137281:50:0::1;;;;;;;:::i;:::-;137349:9;137344:98;137364:17:::0;;::::1;137344:98;;;137426:4;137403:9;:20;137413:6;;137420:1;137413:9;;;;;;;:::i;:::-;;;;;;;137403:20;;;;;;;;;;;;:27;;;;;;;;;;;;;;;;;;137383:3;;;;;:::i;:::-;;;;137344:98;;86229:264:::0;86329:26;:24;:26::i;:::-;86366:25;:23;:25::i;:::-;86402:13;;;;:5;;:13;;;;;:::i;:::-;-1:-1:-1;86426:17:0;;;;:7;;:17;;;;;:::i;:::-;-1:-1:-1;86673:1:0;86454:13;:31;-1:-1:-1;;86229:264:0:o;112276:149::-;112360:18;112373:4;112360:12;:18::i;:::-;109909:30;109920:4;74235:10;109909;:30::i;:::-;112391:26:::1;112403:4;112409:7;112391:11;:26::i;124151:195::-:0;124237:9;124232:107;124252:19;;;124232:107;;;124293:34;124309:4;124315:8;;124324:1;124315:11;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;124293:34::-;124273:3;;;;:::i;:::-;;;;124232:107;;140980:181;141026:13;141052:21;141076:10;:8;:10::i;:::-;141052:34;;141128:7;141111:41;;;;;;;;:::i;:::-;;;;;;;;;;;;;141097:56;;;140980:181;:::o;135460:402::-;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;135686:11:::1;135727:9;135710:27;;;;;;;;:::i;:::-;;;;;;;;;;;;;135700:38;;;;;;135686:52;;135754:9;135749:106;135773:7;:14;135769:1;:18;135749:106;;;135809:34;135832:7;135840:1;135832:10;;;;;;;;:::i;:::-;;;;;;;135809;:15;135820:3;135809:15;;;;;;;;;;;:22;;:34;;;;:::i;:::-;-1:-1:-1::0;135789:3:0;::::1;::::0;::::1;:::i;:::-;;;;135749:106;;133885:315:::0;109463:4;109909:30;109463:4;74235:10;109909;:30::i;:::-;134094:11:::1;134135:9;134118:27;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;134118:27:0;;::::1;::::0;;;;;;134108:38;;134118:27:::1;134108:38:::0;;::::1;::::0;134157:14:::1;::::0;;;:9:::1;:14:::0;;;;;:35;;;::::1;;-1:-1:-1::0;;;134157:35:0::1;-1:-1:-1::0;;;;134157:35:0;;::::1;::::0;;;::::1;::::0;;;-1:-1:-1;;;133885:315:0:o;116208:225::-;116293:4;-1:-1:-1;;;;;;116317:68:0;;-1:-1:-1;;;116317:68:0;;:108;;;116389:36;116413:11;116389:23;:36::i;127396:354::-;127486:18;;-1:-1:-1;;;127486:18:0;;;;127478:41;;;;-1:-1:-1;;;127478:41:0;;39933:2:1;127478:41:0;;;39915:21:1;39972:2;39952:18;;;39945:30;-1:-1:-1;;;39991:18:1;;;39984:40;40041:18;;127478:41:0;39731:334:1;127478:41:0;127538:15;;-1:-1:-1;;;127538:15:0;;;;-1:-1:-1;;127538:25:0;127530:50;;;;-1:-1:-1;;;127530:50:0;;40272:2:1;127530:50:0;;;40254:21:1;40311:2;40291:18;;;40284:30;-1:-1:-1;;;40330:18:1;;;40323:42;40382:18;;127530:50:0;40070:336:1;127530:50:0;127596:6;:20;;;;;;127591:108;;127641:9;127654:10;127641:23;127633:54;;;;-1:-1:-1;;;127633:54:0;;40613:2:1;127633:54:0;;;40595:21:1;40652:2;40632:18;;;40625:30;-1:-1:-1;;;40671:18:1;;;40664:48;40729:18;;127633:54:0;40411:342:1;127633:54:0;127709:33;;127735:6;;127709:33;;:15;;:33;;127735:6;;-1:-1:-1;;;127709:33:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;127396:354;;:::o;43534:167::-;43614:4;43638:55;43648:3;-1:-1:-1;;;;;43668:23:0;;43638:9;:55::i;126612:232::-;126689:6;:16;-1:-1:-1;;;126689:16:0;;-1:-1:-1;;;;;126689:16:0;:21;126685:105;;126761:6;:16;-1:-1:-1;;;126761:16:0;;-1:-1:-1;;;;;126761:16:0;126751:6;126735:13;:11;:13::i;:::-;:22;;;;:::i;:::-;:42;;126727:51;;;;;;126800:23;126806:8;126816:6;126800:5;:23::i;94654:213::-;94711:4;94767:7;86673:1;94748:26;;:66;;;;;94801:13;;94791:7;:23;94748:66;:111;;;;-1:-1:-1;;94832:20:0;;;;:11;:20;;;;;:27;-1:-1:-1;;;94832:27:0;;;;94831:28;;94654:213::o;104109:196::-;104224:24;;;;:15;:24;;;;;;:29;;-1:-1:-1;;;;;;104224:29:0;-1:-1:-1;;;;;104224:29:0;;;;;;;;;104269:28;;104224:24;;104269:28;;;;;;;104109:196;;;:::o;110775:527::-;110864:22;110872:4;110878:7;110864;:22::i;:::-;110859:436;;111052:52;111091:7;-1:-1:-1;;;;;111052:52:0;111101:2;111052:30;:52::i;:::-;111177:49;111216:4;111223:2;111177:30;:49::i;:::-;110957:292;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;110957:292:0;;;;;;;;;;-1:-1:-1;;;110903:380:0;;;;;;;:::i;42962:152::-;43032:4;43056:50;43061:3;-1:-1:-1;;;;;43081:23:0;;43056:4;:50::i;132425:129::-;132485:7;132512:34;132541:4;32267:58;;-1:-1:-1;;;32267:58:0;;;44525:80:1;44621:12;;;44614:28;;;32134:7:0;;44658:12:1;;32267:58:0;;;;;;;;;;;;32257:69;;;;;;32250:76;;32065:269;;;;28263:231;28341:7;28362:17;28381:18;28403:27;28414:4;28420:9;28403:10;:27::i;:::-;28361:69;;;;28441:18;28453:5;28441:11;:18::i;99057:2130::-;99172:35;99210:21;99223:7;99210:12;:21::i;:::-;99172:59;;99270:4;-1:-1:-1;;;;;99248:26:0;:13;:18;;;-1:-1:-1;;;;;99248:26:0;;99244:67;;99283:28;;-1:-1:-1;;;99283:28:0;;;;;;;;;;;99244:67;99324:22;74235:10;-1:-1:-1;;;;;99350:20:0;;;;:73;;-1:-1:-1;99387:36:0;99404:4;74235:10;93215:214;:::i;99387:36::-;99350:126;;;-1:-1:-1;74235:10:0;99440:20;99452:7;99440:11;:20::i;:::-;-1:-1:-1;;;;;99440:36:0;;99350:126;99324:153;;99495:17;99490:66;;99521:35;;-1:-1:-1;;;99521:35:0;;;;;;;;;;;99490:66;-1:-1:-1;;;;;99571:16:0;;99567:52;;99596:23;;-1:-1:-1;;;99596:23:0;;;;;;;;;;;99567:52;99740:35;99757:1;99761:7;99770:4;99740:8;:35::i;:::-;-1:-1:-1;;;;;100071:18:0;;;;;;;:12;:18;;;;;;;;:31;;-1:-1:-1;;;;;;100071:31:0;;;-1:-1:-1;;;;;100071:31:0;;;-1:-1:-1;;100071:31:0;;;;;;;100117:16;;;;;;;;;:29;;;;;;;;-1:-1:-1;100117:29:0;;;;;;;;;;;100197:20;;;:11;:20;;;;;;100232:18;;-1:-1:-1;;;;;;100265:49:0;;;;-1:-1:-1;;;100298:15:0;100265:49;;;;;;;;;;100588:11;;100648:24;;;;;100691:13;;100197:20;;100648:24;;100691:13;100687:384;;100901:13;;100886:11;:28;100882:174;;100939:20;;101008:28;;;;-1:-1:-1;;;;;100982:54:0;-1:-1:-1;;;100982:54:0;-1:-1:-1;;;;;;100982:54:0;;;-1:-1:-1;;;;;100939:20:0;;100982:54;;;;100882:174;100046:1036;;;101118:7;101114:2;-1:-1:-1;;;;;101099:27:0;101108:4;-1:-1:-1;;;;;101099:27:0;-1:-1:-1;;;;;;;;;;;101099:27:0;;;;;;;;;101137:42;124354:197;89521:1141;89610:21;;:::i;:::-;89664:7;;86673:1;89713:23;;:47;;;;;89747:13;;89740:4;:20;89713:47;89709:886;;;89781:31;89815:17;;;:11;:17;;;;;;;;;89781:51;;;;;;;;;-1:-1:-1;;;;;89781:51:0;;;;-1:-1:-1;;;89781:51:0;;-1:-1:-1;;;;;89781:51:0;;;;;;;;-1:-1:-1;;;89781:51:0;;;;;;;;;;;;;;89851:729;;89901:14;;-1:-1:-1;;;;;89901:28:0;;89897:101;;89965:9;89521:1141;-1:-1:-1;;;89521:1141:0:o;89897:101::-;-1:-1:-1;;;90340:6:0;90385:17;;;;:11;:17;;;;;;;;;90373:29;;;;;;;;;-1:-1:-1;;;;;90373:29:0;;;;;-1:-1:-1;;;90373:29:0;;-1:-1:-1;;;;;90373:29:0;;;;;;;;-1:-1:-1;;;90373:29:0;;;;;;;;;;;;;90433:28;90429:109;;90501:9;89521:1141;-1:-1:-1;;;89521:1141:0:o;90429:109::-;90300:261;;;89762:833;89709:886;90623:31;;-1:-1:-1;;;90623:31:0;;;;;;;;;;;117594:169;117682:31;117699:4;117705:7;117682:16;:31::i;:::-;117724:18;;;;:12;:18;;;;;:31;;117747:7;117724:22;:31::i;44966:266::-;45029:16;45058:22;45083:19;45091:3;45083:7;:19::i;117857:174::-;117946:32;117964:4;117970:7;117946:17;:32::i;:::-;117989:18;;;;:12;:18;;;;;:34;;118015:7;117989:25;:34::i;137829:130::-;137892:16;;;;:9;:16;;;;;;;;137891:17;137883:34;;;;-1:-1:-1;;;137883:34:0;;;;;;41977:2:1;41959:21;;;42016:1;41996:18;;;41989:29;-1:-1:-1;;;42049:2:1;42034:18;;42027:34;42093:2;42078:18;;41775:327;137883:34:0;137928:16;;;;:9;:16;;;;;:23;;-1:-1:-1;;137928:23:0;137947:4;137928:23;;;137829:130::o;132793:212::-;132930:4;132954:43;132973:11;132986:4;132992;132954:18;:43::i;:::-;132947:50;132793:212;-1:-1:-1;;;;132793:212:0:o;17564:211::-;17681:86;17701:5;17731:23;;;17756:2;17760:5;17708:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;17708:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;17708:58:0;-1:-1:-1;;;;;;17708:58:0;;;;;;;;;;17681:19;:86::i;44258:158::-;44332:7;44383:22;44387:3;44399:5;44383:3;:22::i;71605:125::-;71653:4;71678:44;71716:4;71678:29;:44::i;:::-;71677:45;71670:52;;71605:125;:::o;141556:216::-;141638:34;:32;:34::i;:::-;141683:28;141698:4;141704:6;141683:14;:28::i;:::-;141722:42;:40;:42::i;113809:112::-;113888:25;113899:4;113905:7;113888:10;:25::i;9597:326::-;-1:-1:-1;;;;;9892:19:0;;:23;;;9597:326::o;104797:772::-;104994:155;;-1:-1:-1;;;104994:155:0;;104960:4;;-1:-1:-1;;;;;104994:36:0;;;;;:155;;74235:10;;105080:4;;105103:7;;105129:5;;104994:155;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;104994:155:0;;;;;;;;-1:-1:-1;;104994:155:0;;;;;;;;;;;;:::i;:::-;;;104977:585;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105320:6;:13;105337:1;105320:18;105316:235;;105366:40;;-1:-1:-1;;;105366:40:0;;;;;;;;;;;105316:235;105509:6;105503:13;105494:6;105490:2;105486:15;105479:38;104977:585;-1:-1:-1;;;;;;105205:55:0;-1:-1:-1;;;105205:55:0;;-1:-1:-1;104797:772:0;;;;;;:::o;141780:114::-;141840:13;141873;141866:20;;;;;:::i;54782:723::-;54838:13;55059:5;55068:1;55059:10;55055:53;;-1:-1:-1;;55086:10:0;;;;;;;;;;;;-1:-1:-1;;;55086:10:0;;;;;54782:723::o;55055:53::-;55133:5;55118:12;55174:78;55181:9;;55174:78;;55207:8;;;;:::i;:::-;;-1:-1:-1;55230:10:0;;-1:-1:-1;55238:2:0;55230:10;;:::i;:::-;;;55174:78;;;55262:19;55294:6;-1:-1:-1;;;;;55284:17:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;55284:17:0;;55262:39;;55312:154;55319:10;;55312:154;;55346:11;55356:1;55346:11;;:::i;:::-;;-1:-1:-1;55415:10:0;55423:2;55415:5;:10;:::i;:::-;55402:24;;:2;:24;:::i;:::-;55389:39;;55372:6;55379;55372:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;55372:56:0;;;;;;;;-1:-1:-1;55443:11:0;55452:2;55443:11;;:::i;:::-;;;55312:154;;43787:117;43850:7;43877:19;43885:3;39271:18;;39188:109;74079:70;71516:13;;;;;;;71508:69;;;;-1:-1:-1;;;71508:69:0;;;;;;;:::i;:::-;74079:70::o;43290:158::-;43363:4;43387:53;43395:3;-1:-1:-1;;;;;43415:23:0;;43387:7;:53::i;110031:215::-;110116:4;-1:-1:-1;;;;;;110140:58:0;;-1:-1:-1;;;110140:58:0;;:98;;;110202:36;110226:11;110202:23;:36::i;38973:129::-;39046:4;39070:19;;;:12;;;;;:19;;;;;;:24;;;38973:129::o;97629:1174::-;97717:13;;-1:-1:-1;;;;;97745:16:0;;97741:48;;97770:19;;-1:-1:-1;;;97770:19:0;;;;;;;;;;;97741:48;97804:8;97816:1;97804:13;97800:44;;97826:18;;-1:-1:-1;;;97826:18:0;;;;;;;;;;;97800:44;-1:-1:-1;;;;;98195:16:0;;;;;;:12;:16;;;;;;;;:44;;-1:-1:-1;;;;;;98254:49:0;;-1:-1:-1;;;;;98195:44:0;;;;;;;98254:49;;;-1:-1:-1;;;;;;;;;98195:44:0;;;;;;98254:49;;;;;;;;;;;;;;;;98320:25;;;:11;:25;;;;;;:35;;-1:-1:-1;;;;;;98370:66:0;;;;-1:-1:-1;;;98420:15:0;98370:66;;;;;;;;;;98320:25;98517:23;;;98557:112;98584:40;;98609:14;;;;;-1:-1:-1;;;;;98584:40:0;;;98601:1;;-1:-1:-1;;;;;;;;;;;98584:40:0;98601:1;;98584:40;98664:3;98648:12;:19;98557:112;;-1:-1:-1;98685:13:0;:28;92141:301;92079:363;;:::o;56083:451::-;56158:13;56184:19;56216:10;56220:6;56216:1;:10;:::i;:::-;:14;;56229:1;56216:14;:::i;:::-;-1:-1:-1;;;;;56206:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;56206:25:0;;56184:47;;-1:-1:-1;;;56242:6:0;56249:1;56242:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;56242:15:0;;;;;;;;;-1:-1:-1;;;56268:6:0;56275:1;56268:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;56268:15:0;;;;;;;;-1:-1:-1;56299:9:0;56311:10;56315:6;56311:1;:10;:::i;:::-;:14;;56324:1;56311:14;:::i;:::-;56299:26;;56294:135;56331:1;56327;:5;56294:135;;;-1:-1:-1;;;56379:5:0;56387:3;56379:11;56366:25;;;;;;;:::i;:::-;;;;56354:6;56361:1;56354:9;;;;;;;;:::i;:::-;;;;:37;-1:-1:-1;;;;;56354:37:0;;;;;;;;-1:-1:-1;56416:1:0;56406:11;;;;;56334:3;;;:::i;:::-;;;56294:135;;;-1:-1:-1;56447:10:0;;56439:55;;;;-1:-1:-1;;;56439:55:0;;44136:2:1;56439:55:0;;;44118:21:1;;;44155:18;;;44148:30;44214:34;44194:18;;;44187:62;44266:18;;56439:55:0;43934:356:1;36877:414:0;36940:4;36962:21;36972:3;36977:5;36962:9;:21::i;:::-;36957:327;;-1:-1:-1;37000:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;37183:18;;37161:19;;;:12;;;:19;;;;;;:40;;;;37216:11;;36957:327;-1:-1:-1;37267:5:0;37260:12;;26153:1308;26234:7;26243:12;26468:9;:16;26488:2;26468:22;26464:990;;26764:4;26749:20;;26743:27;26814:4;26799:20;;26793:27;26872:4;26857:20;;26851:27;26507:9;26843:36;26915:25;26926:4;26843:36;26743:27;26793;26915:10;:25::i;:::-;26908:32;;;;;;;;;26464:990;26962:9;:16;26982:2;26962:22;26958:496;;27237:4;27222:20;;27216:27;27288:4;27273:20;;27267:27;27330:23;27341:4;27216:27;27267;27330:10;:23::i;:::-;27323:30;;;;;;;;26958:496;-1:-1:-1;27402:1:0;;-1:-1:-1;27406:35:0;26958:496;26153:1308;;;;;:::o;24424:643::-;24502:20;24493:5;:29;;;;;;;;:::i;:::-;;24489:571;;24424:643;:::o;24489:571::-;24600:29;24591:5;:38;;;;;;;;:::i;:::-;;24587:473;;24646:34;;-1:-1:-1;;;24646:34:0;;45015:2:1;24646:34:0;;;44997:21:1;45054:2;45034:18;;;45027:30;-1:-1:-1;;;45073:18:1;;;45066:54;45137:18;;24646:34:0;44813:348:1;24587:473:0;24711:35;24702:5;:44;;;;;;;;:::i;:::-;;24698:362;;24763:41;;-1:-1:-1;;;24763:41:0;;45368:2:1;24763:41:0;;;45350:21:1;45407:2;45387:18;;;45380:30;45446:33;45426:18;;;45419:61;45497:18;;24763:41:0;45166:355:1;24698:362:0;24835:30;24826:5;:39;;;;;;;;:::i;:::-;;24822:238;;24882:44;;-1:-1:-1;;;24882:44:0;;45728:2:1;24882:44:0;;;45710:21:1;45767:2;45747:18;;;45740:30;45806:34;45786:18;;;45779:62;-1:-1:-1;;;45857:18:1;;;45850:32;45899:19;;24882:44:0;45526:398:1;24822:238:0;24957:30;24948:5;:39;;;;;;;;:::i;:::-;;24944:116;;25004:44;;-1:-1:-1;;;25004:44:0;;46131:2:1;25004:44:0;;;46113:21:1;46170:2;46150:18;;;46143:30;46209:34;46189:18;;;46182:62;-1:-1:-1;;;46260:18:1;;;46253:32;46302:19;;25004:44:0;45929:398:1;24944:116:0;24424:643;:::o;114433:238::-;114517:22;114525:4;114531:7;114517;:22::i;:::-;114512:152;;114556:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;114556:29:0;;;;;;;;;:36;;-1:-1:-1;;114556:36:0;114588:4;114556:36;;;114639:12;74235:10;;74155:98;114639:12;-1:-1:-1;;;;;114612:40:0;114630:7;-1:-1:-1;;;;;114612:40:0;114624:4;114612:40;;;;;;;;;;114433:238;;:::o;40321:111::-;40377:16;40413:3;:11;;40406:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40321:111;;;:::o;114803:239::-;114887:22;114895:4;114901:7;114887;:22::i;:::-;114883:152;;;114958:5;114926:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;114926:29:0;;;;;;;;;;:37;;-1:-1:-1;;114926:37:0;;;114983:40;74235:10;;114926:12;;114983:40;;114958:5;114983:40;114803:239;;:::o;6182:190::-;6307:4;6360;6331:25;6344:5;6351:4;6331:12;:25::i;:::-;:33;;6182:190;-1:-1:-1;;;;6182:190:0:o;20137:716::-;20561:23;20587:69;20615:4;20587:69;;;;;;;;;;;;;;;;;20595:5;-1:-1:-1;;;;;20587:27:0;;;:69;;;;;:::i;:::-;20671:17;;20561:95;;-1:-1:-1;20671:21:0;20667:179;;20768:10;20757:30;;;;;;;;;;;;:::i;:::-;20749:85;;;;-1:-1:-1;;;20749:85:0;;46784:2:1;20749:85:0;;;46766:21:1;46823:2;46803:18;;;46796:30;46862:34;46842:18;;;46835:62;-1:-1:-1;;;46913:18:1;;;46906:40;46963:19;;20749:85:0;46582:406:1;39651:120:0;39718:7;39745:3;:11;;39757:5;39745:18;;;;;;;;:::i;:::-;;;;;;;;;39738:25;;39651:120;;;;:::o;120364:111::-;71516:13;;;;;;;71508:69;;;;-1:-1:-1;;;71508:69:0;;;;;;;:::i;:::-;120157:1:::1;120445:7;:22:::0;120364:111::o;37467:1420::-;37533:4;37672:19;;;:12;;;:19;;;;;;37708:15;;37704:1176;;38083:21;38107:14;38120:1;38107:10;:14;:::i;:::-;38156:18;;38083:38;;-1:-1:-1;38136:17:0;;38156:22;;38177:1;;38156:22;:::i;:::-;38136:42;;38212:13;38199:9;:26;38195:405;;38246:17;38266:3;:11;;38278:9;38266:22;;;;;;;;:::i;:::-;;;;;;;;;38246:42;;38420:9;38391:3;:11;;38403:13;38391:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;38505:23;;;:12;;;:23;;;;;:36;;;38195:405;38681:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;38776:3;:12;;:19;38789:5;38776:19;;;;;;;;;;;38769:26;;;38819:4;38812:11;;;;;;;37704:1176;38863:5;38856:12;;;;;87677:399;87846:4;-1:-1:-1;;;;;;87888:51:0;;-1:-1:-1;;;87888:51:0;;:127;;-1:-1:-1;;;;;;;87956:59:0;;-1:-1:-1;;;87956:59:0;87888:127;:180;;;-1:-1:-1;;;;;;;;;;72915:51:0;;;88032:36;72806:168;29715:1632;29846:7;;-1:-1:-1;;;;;30767:79:0;;30763:163;;;-1:-1:-1;30879:1:0;;-1:-1:-1;30883:30:0;30863:51;;30763:163;30940:1;:7;;30945:2;30940:7;;:18;;;;;30951:1;:7;;30956:2;30951:7;;30940:18;30936:102;;;-1:-1:-1;30991:1:0;;-1:-1:-1;30995:30:0;30975:51;;30936:102;31152:24;;;31135:14;31152:24;;;;;;;;;47352:25:1;;;47425:4;47413:17;;47393:18;;;47386:45;;;;47447:18;;;47440:34;;;47490:18;;;47483:34;;;31152:24:0;;47324:19:1;;31152:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;31152:24:0;;-1:-1:-1;;31152:24:0;;;-1:-1:-1;;;;;;;31191:20:0;;31187:103;;31244:1;31248:29;31228:50;;;;;;;31187:103;31310:6;-1:-1:-1;31318:20:0;;-1:-1:-1;29715:1632:0;;;;;;;;:::o;28757:344::-;28871:7;;-1:-1:-1;;;;;28917:80:0;;28871:7;29024:25;29040:3;29025:18;;;29047:2;29024:25;:::i;:::-;29008:42;;29068:25;29079:4;29085:1;29088;29091;29068:10;:25::i;:::-;29061:32;;;;;;28757:344;;;;;;:::o;6734:675::-;6817:7;6860:4;6817:7;6875:497;6899:5;:12;6895:1;:16;6875:497;;;6933:20;6956:5;6962:1;6956:8;;;;;;;;:::i;:::-;;;;;;;6933:31;;6999:12;6983;:28;6979:382;;7485:13;7535:15;;;7571:4;7564:15;;;7618:4;7602:21;;7111:57;;6979:382;;;7485:13;7535:15;;;7571:4;7564:15;;;7618:4;7602:21;;7288:57;;6979:382;-1:-1:-1;6913:3:0;;;;:::i;:::-;;;;6875:497;;12342:229;12479:12;12511:52;12533:6;12541:4;12547:1;12550:12;12479;13757:18;13768:6;13757:10;:18::i;:::-;13749:60;;;;-1:-1:-1;;;13749:60:0;;48137:2:1;13749:60:0;;;48119:21:1;48176:2;48156:18;;;48149:30;48215:31;48195:18;;;48188:59;48264:18;;13749:60:0;47935:353:1;13749:60:0;13823:12;13837:23;13864:6;-1:-1:-1;;;;;13864:11:0;13883:5;13890:4;13864:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13822:73;;;;13913:51;13930:7;13939:10;13951:12;13913:16;:51::i;:::-;13906:58;13462:510;-1:-1:-1;;;;;;;13462:510:0:o;16148:712::-;16298:12;16327:7;16323:530;;;-1:-1:-1;16358:10:0;16351:17;;16323:530;16472:17;;:21;16468:374;;16670:10;16664:17;16731:15;16718:10;16714:2;16710:19;16703:44;16468:374;16813:12;16806:20;;-1:-1:-1;;;16806:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;14:131:1;-1:-1:-1;;;;;;88:32:1;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;688:127::-;749:10;744:3;740:20;737:1;730:31;780:4;777:1;770:15;804:4;801:1;794:15;820:275;891:2;885:9;956:2;937:13;;-1:-1:-1;;933:27:1;921:40;;-1:-1:-1;;;;;976:34:1;;1012:22;;;973:62;970:88;;;1038:18;;:::i;:::-;1074:2;1067:22;820:275;;-1:-1:-1;820:275:1:o;1100:531::-;1143:5;1196:3;1189:4;1181:6;1177:17;1173:27;1163:55;;1214:1;1211;1204:12;1163:55;1237:20;;-1:-1:-1;;;;;1269:26:1;;1266:52;;;1298:18;;:::i;:::-;1342:55;1385:2;1366:13;;-1:-1:-1;;1362:27:1;1391:4;1358:38;1342:55;:::i;:::-;1422:2;1413:7;1406:19;1468:3;1461:4;1456:2;1448:6;1444:15;1440:26;1437:35;1434:55;;;1485:1;1482;1475:12;1434:55;1550:2;1543:4;1535:6;1531:17;1524:4;1515:7;1511:18;1498:55;1598:1;1573:16;;;1591:4;1569:27;1562:38;;;;1577:7;1100:531;-1:-1:-1;;;1100:531:1:o;1636:390::-;1714:6;1722;1775:2;1763:9;1754:7;1750:23;1746:32;1743:52;;;1791:1;1788;1781:12;1743:52;1818:23;;-1:-1:-1;;;;;1853:30:1;;1850:50;;;1896:1;1893;1886:12;1850:50;1919;1961:7;1952:6;1941:9;1937:22;1919:50;:::i;:::-;1909:60;2016:2;2001:18;;;;1988:32;;-1:-1:-1;;;;1636:390:1:o;2031:258::-;2103:1;2113:113;2127:6;2124:1;2121:13;2113:113;;;2203:11;;;2197:18;2184:11;;;2177:39;2149:2;2142:10;2113:113;;;2244:6;2241:1;2238:13;2235:48;;;-1:-1:-1;;2279:1:1;2261:16;;2254:27;2031:258::o;2294:::-;2336:3;2374:5;2368:12;2401:6;2396:3;2389:19;2417:63;2473:6;2466:4;2461:3;2457:14;2450:4;2443:5;2439:16;2417:63;:::i;:::-;2534:2;2513:15;-1:-1:-1;;2509:29:1;2500:39;;;;2541:4;2496:50;;2294:258;-1:-1:-1;;2294:258:1:o;2557:220::-;2706:2;2695:9;2688:21;2669:4;2726:45;2767:2;2756:9;2752:18;2744:6;2726:45;:::i;2782:180::-;2841:6;2894:2;2882:9;2873:7;2869:23;2865:32;2862:52;;;2910:1;2907;2900:12;2862:52;-1:-1:-1;2933:23:1;;2782:180;-1:-1:-1;2782:180:1:o;3076:203::-;-1:-1:-1;;;;;3240:32:1;;;;3222:51;;3210:2;3195:18;;3076:203::o;3284:131::-;-1:-1:-1;;;;;3359:31:1;;3349:42;;3339:70;;3405:1;3402;3395:12;3420:315;3488:6;3496;3549:2;3537:9;3528:7;3524:23;3520:32;3517:52;;;3565:1;3562;3555:12;3517:52;3604:9;3591:23;3623:31;3648:5;3623:31;:::i;:::-;3673:5;3725:2;3710:18;;;;3697:32;;-1:-1:-1;;;3420:315:1:o;3740:592::-;3792:3;3823;3855:5;3849:12;3882:6;3877:3;3870:19;3908:4;3937:2;3932:3;3928:12;3921:19;;3993:2;3983:6;3980:1;3976:14;3969:5;3965:26;3961:35;4030:2;4023:5;4019:14;4051:1;4061:245;4075:6;4072:1;4069:13;4061:245;;;4162:2;4158:7;4150:5;4144:4;4140:16;4136:30;4131:3;4124:43;4188:38;4221:4;4212:6;4206:13;4188:38;:::i;:::-;4284:12;;;;4180:46;-1:-1:-1;4249:15:1;;;;4097:1;4090:9;4061:245;;;-1:-1:-1;4322:4:1;;3740:592;-1:-1:-1;;;;;;;3740:592:1:o;4337:280::-;4536:2;4525:9;4518:21;4499:4;4556:55;4607:2;4596:9;4592:18;4584:6;4556:55;:::i;4622:183::-;4682:4;-1:-1:-1;;;;;4704:30:1;;4701:56;;;4737:18;;:::i;:::-;-1:-1:-1;4782:1:1;4778:14;4794:4;4774:25;;4622:183::o;4810:1187::-;4913:6;4921;4974:2;4962:9;4953:7;4949:23;4945:32;4942:52;;;4990:1;4987;4980:12;4942:52;5017:23;;-1:-1:-1;;;;;5089:14:1;;;5086:34;;;5116:1;5113;5106:12;5086:34;5139:50;5181:7;5172:6;5161:9;5157:22;5139:50;:::i;:::-;5129:60;;5208:2;5198:12;;5263:2;5252:9;5248:18;5235:32;5292:2;5282:8;5279:16;5276:36;;;5308:1;5305;5298:12;5276:36;5331:24;;;-1:-1:-1;5386:4:1;5378:13;;5374:27;-1:-1:-1;5364:55:1;;5415:1;5412;5405:12;5364:55;5451:2;5438:16;5474:60;5490:43;5530:2;5490:43;:::i;:::-;5474:60;:::i;:::-;5568:15;;;5650:1;5646:10;;;;5638:19;;5634:28;;;5599:12;;;;5674:19;;;5671:39;;;5706:1;5703;5696:12;5671:39;5730:11;;;;5750:217;5766:6;5761:3;5758:15;5750:217;;;5846:3;5833:17;5863:31;5888:5;5863:31;:::i;:::-;5907:18;;5783:12;;;;5945;;;;5750:217;;;5986:5;5976:15;;;;;;;4810:1187;;;;;:::o;6184:367::-;6247:8;6257:6;6311:3;6304:4;6296:6;6292:17;6288:27;6278:55;;6329:1;6326;6319:12;6278:55;-1:-1:-1;6352:20:1;;-1:-1:-1;;;;;6384:30:1;;6381:50;;;6427:1;6424;6417:12;6381:50;6464:4;6456:6;6452:17;6440:29;;6524:3;6517:4;6507:6;6504:1;6500:14;6492:6;6488:27;6484:38;6481:47;6478:67;;;6541:1;6538;6531:12;6556:505;6651:6;6659;6667;6720:2;6708:9;6699:7;6695:23;6691:32;6688:52;;;6736:1;6733;6726:12;6688:52;6759:23;;;-1:-1:-1;6833:2:1;6818:18;;6805:32;-1:-1:-1;;;;;6849:30:1;;6846:50;;;6892:1;6889;6882:12;6846:50;6931:70;6993:7;6984:6;6973:9;6969:22;6931:70;:::i;:::-;6556:505;;7020:8;;-1:-1:-1;6905:96:1;;-1:-1:-1;;;;6556:505:1:o;7066:389::-;7143:6;7151;7204:2;7192:9;7183:7;7179:23;7175:32;7172:52;;;7220:1;7217;7210:12;7172:52;7243:23;;;-1:-1:-1;7317:2:1;7302:18;;7289:32;-1:-1:-1;;;;;7333:30:1;;7330:50;;;7376:1;7373;7366:12;7330:50;7399;7441:7;7432:6;7421:9;7417:22;7399:50;:::i;:::-;7389:60;;;7066:389;;;;;:::o;7460:247::-;7519:6;7572:2;7560:9;7551:7;7547:23;7543:32;7540:52;;;7588:1;7585;7578:12;7540:52;7627:9;7614:23;7646:31;7671:5;7646:31;:::i;7712:632::-;7883:2;7935:21;;;8005:13;;7908:18;;;8027:22;;;7854:4;;7883:2;8106:15;;;;8080:2;8065:18;;;7854:4;8149:169;8163:6;8160:1;8157:13;8149:169;;;8224:13;;8212:26;;8293:15;;;;8258:12;;;;8185:1;8178:9;8149:169;;8349:456;8426:6;8434;8442;8495:2;8483:9;8474:7;8470:23;8466:32;8463:52;;;8511:1;8508;8501:12;8463:52;8550:9;8537:23;8569:31;8594:5;8569:31;:::i;:::-;8619:5;-1:-1:-1;8676:2:1;8661:18;;8648:32;8689:33;8648:32;8689:33;:::i;:::-;8349:456;;8741:7;;-1:-1:-1;;;8795:2:1;8780:18;;;;8767:32;;8349:456::o;9177:315::-;9245:6;9253;9306:2;9294:9;9285:7;9281:23;9277:32;9274:52;;;9322:1;9319;9312:12;9274:52;9358:9;9345:23;9335:33;;9418:2;9407:9;9403:18;9390:32;9431:31;9456:5;9431:31;:::i;:::-;9481:5;9471:15;;;9177:315;;;;;:::o;9497:322::-;9566:6;9619:2;9607:9;9598:7;9594:23;9590:32;9587:52;;;9635:1;9632;9625:12;9587:52;9662:23;;-1:-1:-1;;;;;9697:30:1;;9694:50;;;9740:1;9737;9730:12;9694:50;9763;9805:7;9796:6;9785:9;9781:22;9763:50;:::i;9824:658::-;9995:2;10047:21;;;10117:13;;10020:18;;;10139:22;;;9966:4;;9995:2;10218:15;;;;10192:2;10177:18;;;9966:4;10261:195;10275:6;10272:1;10269:13;10261:195;;;10340:13;;-1:-1:-1;;;;;10336:39:1;10324:52;;10431:15;;;;10396:12;;;;10372:1;10290:9;10261:195;;10487:173;10555:20;;-1:-1:-1;;;;;10604:31:1;;10594:42;;10584:70;;10650:1;10647;10640:12;10584:70;10487:173;;;:::o;10665:163::-;10732:20;;10792:10;10781:22;;10771:33;;10761:61;;10818:1;10815;10808:12;10833:159;10900:20;;10960:6;10949:18;;10939:29;;10929:57;;10982:1;10979;10972:12;10997:118;11083:5;11076:13;11069:21;11062:5;11059:32;11049:60;;11105:1;11102;11095:12;11120:128;11185:20;;11214:28;11185:20;11214:28;:::i;11253:671::-;11353:6;11361;11369;11377;11385;11438:3;11426:9;11417:7;11413:23;11409:33;11406:53;;;11455:1;11452;11445:12;11406:53;11482:23;;-1:-1:-1;;;;;11517:30:1;;11514:50;;;11560:1;11557;11550:12;11514:50;11583;11625:7;11616:6;11605:9;11601:22;11583:50;:::i;:::-;11573:60;;;11652:38;11686:2;11675:9;11671:18;11652:38;:::i;:::-;11642:48;;11709:37;11742:2;11731:9;11727:18;11709:37;:::i;:::-;11699:47;;11765:37;11798:2;11787:9;11783:18;11765:37;:::i;:::-;11755:47;;11852:3;11841:9;11837:19;11824:33;11866:28;11888:5;11866:28;:::i;:::-;11913:5;11903:15;;;11253:671;;;;;;;;:::o;11929:873::-;12051:6;12059;12067;12075;12083;12091;12099;12152:3;12140:9;12131:7;12127:23;12123:33;12120:53;;;12169:1;12166;12159:12;12120:53;12208:9;12195:23;12227:31;12252:5;12227:31;:::i;:::-;12277:5;-1:-1:-1;12329:2:1;12314:18;;12301:32;;-1:-1:-1;12380:2:1;12365:18;;12352:32;;-1:-1:-1;12431:2:1;12416:18;;12403:32;;-1:-1:-1;12482:3:1;12467:19;;12454:33;;-1:-1:-1;12539:3:1;12524:19;;12511:33;12553;12511;12553;:::i;:::-;12605:7;-1:-1:-1;12663:3:1;12648:19;;12635:33;-1:-1:-1;;;;;12680:30:1;;12677:50;;;12723:1;12720;12713:12;12677:50;12746;12788:7;12779:6;12768:9;12764:22;12746:50;:::i;:::-;12736:60;;;11929:873;;;;;;;;;;:::o;12807:1665::-;12964:6;12972;12980;12988;12996;13004;13012;13020;13073:3;13061:9;13052:7;13048:23;13044:33;13041:53;;;13090:1;13087;13080:12;13041:53;13117:23;;-1:-1:-1;;;;;13189:14:1;;;13186:34;;;13216:1;13213;13206:12;13186:34;13239:50;13281:7;13272:6;13261:9;13257:22;13239:50;:::i;:::-;13229:60;;13308:2;13298:12;;13360:2;13349:9;13345:18;13332:32;13373:31;13398:5;13373:31;:::i;:::-;13423:5;-1:-1:-1;13475:2:1;13460:18;;13447:32;;-1:-1:-1;13526:2:1;13511:18;;13498:32;;-1:-1:-1;13577:3:1;13562:19;;13549:33;;-1:-1:-1;13629:3:1;13614:19;;13601:33;;-1:-1:-1;13686:3:1;13671:19;;13658:33;13700;13658;13700;:::i;:::-;13752:7;-1:-1:-1;13812:3:1;13797:19;;13784:33;13829:16;;;13826:36;;;13858:1;13855;13848:12;13826:36;13881:24;;;-1:-1:-1;13936:4:1;13928:13;;13924:27;-1:-1:-1;13914:55:1;;13965:1;13962;13955:12;13914:55;14001:2;13988:16;14024:60;14040:43;14080:2;14040:43;:::i;14024:60::-;14118:15;;;14200:1;14196:10;;;;14188:19;;14184:28;;;14149:12;;;;14224:19;;;14221:39;;;14256:1;14253;14246:12;14221:39;14280:11;;;;14300:142;14316:6;14311:3;14308:15;14300:142;;;14382:17;;14370:30;;14333:12;;;;14420;;;;14300:142;;;14461:5;14451:15;;;;;;;12807:1665;;;;;;;;;;;:::o;14477:1085::-;14598:6;14606;14614;14622;14630;14638;14646;14654;14707:3;14695:9;14686:7;14682:23;14678:33;14675:53;;;14724:1;14721;14714:12;14675:53;14751:23;;-1:-1:-1;;;;;14786:30:1;;14783:50;;;14829:1;14826;14819:12;14783:50;14852;14894:7;14885:6;14874:9;14870:22;14852:50;:::i;:::-;14842:60;;;14921:38;14955:2;14944:9;14940:18;14921:38;:::i;:::-;14911:48;;14978:37;15011:2;15000:9;14996:18;14978:37;:::i;:::-;14968:47;;15034:37;15067:2;15056:9;15052:18;15034:37;:::i;:::-;15024:47;;15121:3;15110:9;15106:19;15093:33;15135:28;15157:5;15135:28;:::i;:::-;15182:5;-1:-1:-1;15239:3:1;15224:19;;15211:33;15253:30;15211:33;15253:30;:::i;:::-;15302:7;-1:-1:-1;15361:3:1;15346:19;;15333:33;15375:30;15333:33;15375:30;:::i;:::-;15424:7;-1:-1:-1;15483:3:1;15468:19;;15455:33;15497;15455;15497;:::i;:::-;15549:7;15539:17;;;14477:1085;;;;;;;;;;;:::o;15567:891::-;15651:6;15682:2;15725;15713:9;15704:7;15700:23;15696:32;15693:52;;;15741:1;15738;15731:12;15693:52;15768:23;;-1:-1:-1;;;;;15803:30:1;;15800:50;;;15846:1;15843;15836:12;15800:50;15869:22;;15922:4;15914:13;;15910:27;-1:-1:-1;15900:55:1;;15951:1;15948;15941:12;15900:55;15987:2;15974:16;16010:60;16026:43;16066:2;16026:43;:::i;16010:60::-;16104:15;;;16186:1;16182:10;;;;16174:19;;16170:28;;;16135:12;;;;16210:19;;;16207:39;;;16242:1;16239;16232:12;16207:39;16266:11;;;;16286:142;16302:6;16297:3;16294:15;16286:142;;;16368:17;;16356:30;;16319:12;;;;16406;;;;16286:142;;16463:278;16547:12;;-1:-1:-1;;;;;16543:38:1;16531:51;;16635:4;16624:16;;;16618:23;-1:-1:-1;;;;;16614:48:1;16598:14;;;16591:72;16651:2;16715:16;;;16709:23;16702:31;16695:39;16679:14;;16672:63;16463:278::o;16746:724::-;16981:2;17033:21;;;17103:13;;17006:18;;;17125:22;;;16952:4;;16981:2;17204:15;;;;17178:2;17163:18;;;16952:4;17247:197;17261:6;17258:1;17255:13;17247:197;;;17310:52;17358:3;17349:6;17343:13;17310:52;:::i;:::-;17419:15;;;;17391:4;17382:14;;;;;17283:1;17276:9;17247:197;;17475:919;17561:6;17569;17577;17585;17593;17601;17654:3;17642:9;17633:7;17629:23;17625:33;17622:53;;;17671:1;17668;17661:12;17622:53;17710:9;17697:23;17729:28;17751:5;17729:28;:::i;:::-;17776:5;-1:-1:-1;17833:2:1;17818:18;;17805:32;17846:30;17805:32;17846:30;:::i;:::-;17895:7;-1:-1:-1;17954:2:1;17939:18;;17926:32;17967:30;17926:32;17967:30;:::i;:::-;18016:7;-1:-1:-1;18075:2:1;18060:18;;18047:32;18088:30;18047:32;18088:30;:::i;:::-;18137:7;-1:-1:-1;18196:3:1;18181:19;;18168:33;18210:30;18168:33;18210:30;:::i;:::-;18259:7;-1:-1:-1;18318:3:1;18303:19;;18290:33;18332:30;18290:33;18332:30;:::i;:::-;18381:7;18371:17;;;17475:919;;;;;;;;:::o;19176:874::-;19298:6;19306;19314;19322;19330;19338;19346;19354;19407:3;19395:9;19386:7;19382:23;19378:33;19375:53;;;19424:1;19421;19414:12;19375:53;19463:9;19450:23;19482:31;19507:5;19482:31;:::i;:::-;19532:5;-1:-1:-1;19584:2:1;19569:18;;19556:32;;-1:-1:-1;19635:2:1;19620:18;;19607:32;;-1:-1:-1;19686:2:1;19671:18;;19658:32;;-1:-1:-1;19737:3:1;19722:19;;19709:33;;-1:-1:-1;19794:3:1;19779:19;;19766:33;19808;19766;19808;:::i;:::-;19860:7;-1:-1:-1;19919:3:1;19904:19;;19891:33;19933;19891;19933;:::i;:::-;19985:7;19975:17;;;20039:3;20028:9;20024:19;20011:33;20001:43;;19176:874;;;;;;;;;;;:::o;20055:248::-;20123:6;20131;20184:2;20172:9;20163:7;20159:23;20155:32;20152:52;;;20200:1;20197;20190:12;20152:52;-1:-1:-1;;20223:23:1;;;20293:2;20278:18;;;20265:32;;-1:-1:-1;20055:248:1:o;20308:806::-;20396:6;20404;20412;20420;20473:2;20461:9;20452:7;20448:23;20444:32;20441:52;;;20489:1;20486;20479:12;20441:52;20516:23;;-1:-1:-1;;;;;20588:14:1;;;20585:34;;;20615:1;20612;20605:12;20585:34;20653:6;20642:9;20638:22;20628:32;;20698:7;20691:4;20687:2;20683:13;20679:27;20669:55;;20720:1;20717;20710:12;20669:55;20760:2;20747:16;20786:2;20778:6;20775:14;20772:34;;;20802:1;20799;20792:12;20772:34;20849:7;20842:4;20833:6;20829:2;20825:15;20821:26;20818:39;20815:59;;;20870:1;20867;20860:12;20815:59;20901:4;20893:13;;;;-1:-1:-1;20925:6:1;-1:-1:-1;20950:40:1;;20969:20;;;-1:-1:-1;20950:40:1;:::i;:::-;20940:50;;21040:2;21029:9;21025:18;21012:32;21053:31;21078:5;21053:31;:::i;:::-;20308:806;;;;-1:-1:-1;20308:806:1;;-1:-1:-1;;20308:806:1:o;21119:959::-;21334:13;;-1:-1:-1;;;;;21330:39:1;21312:58;;21430:4;21418:17;;;21412:24;21438:10;21408:41;21386:20;;;21379:71;21510:4;21498:17;;;21492:24;21518:6;21488:37;21466:20;;;21459:67;21596:4;21584:17;;;21578:24;21571:32;21564:40;21542:20;;;21535:70;21357:3;21640:17;;;21634:24;21299:3;21284:19;;;21667:51;;21697:20;;21634:24;470:13;463:21;451:34;;400:91;21667:51;;21767:4;21759:6;21755:17;21749:24;21782:53;21829:4;21818:9;21814:20;21798:14;470:13;463:21;451:34;;400:91;21782:53;;21884:4;21876:6;21872:17;21866:24;21899:53;21946:4;21935:9;21931:20;21915:14;470:13;463:21;451:34;;400:91;21899:53;;22001:4;21993:6;21989:17;21983:24;22016:56;22066:4;22055:9;22051:20;22035:14;-1:-1:-1;;;;;3033:31:1;3021:44;;2967:104;22083:383;22160:6;22168;22176;22229:2;22217:9;22208:7;22204:23;22200:32;22197:52;;;22245:1;22242;22235:12;22197:52;22284:9;22271:23;22303:31;22328:5;22303:31;:::i;:::-;22353:5;22405:2;22390:18;;22377:32;;-1:-1:-1;22456:2:1;22441:18;;;22428:32;;22083:383;-1:-1:-1;;;22083:383:1:o;22471:284::-;22529:6;22582:2;22570:9;22561:7;22557:23;22553:32;22550:52;;;22598:1;22595;22588:12;22550:52;22624:23;;-1:-1:-1;;;;;22676:30:1;;22666:41;;22656:69;;22721:1;22718;22711:12;22760:437;22846:6;22854;22907:2;22895:9;22886:7;22882:23;22878:32;22875:52;;;22923:1;22920;22913:12;22875:52;22950:23;;-1:-1:-1;;;;;22985:30:1;;22982:50;;;23028:1;23025;23018:12;22982:50;23067:70;23129:7;23120:6;23109:9;23105:22;23067:70;:::i;:::-;23156:8;;23041:96;;-1:-1:-1;22760:437:1;-1:-1:-1;;;;22760:437:1:o;23202:382::-;23267:6;23275;23328:2;23316:9;23307:7;23303:23;23299:32;23296:52;;;23344:1;23341;23334:12;23296:52;23383:9;23370:23;23402:31;23427:5;23402:31;:::i;:::-;23452:5;-1:-1:-1;23509:2:1;23494:18;;23481:32;23522:30;23481:32;23522:30;:::i;23589:823::-;23866:2;23855:9;23848:21;23829:4;23892:55;23943:2;23932:9;23928:18;23920:6;23892:55;:::i;:::-;24004:22;;;23966:2;23984:18;;;23977:50;;;;24076:13;;24098:22;;;24174:15;;;;24136;;;24207:1;24217:169;24231:6;24228:1;24225:13;24217:169;;;24292:13;;24280:26;;24361:15;;;;24326:12;;;;24253:1;24246:9;24217:169;;24812:666;24907:6;24915;24923;24931;24984:3;24972:9;24963:7;24959:23;24955:33;24952:53;;;25001:1;24998;24991:12;24952:53;25040:9;25027:23;25059:31;25084:5;25059:31;:::i;:::-;25109:5;-1:-1:-1;25166:2:1;25151:18;;25138:32;25179:33;25138:32;25179:33;:::i;:::-;25231:7;-1:-1:-1;25285:2:1;25270:18;;25257:32;;-1:-1:-1;25340:2:1;25325:18;;25312:32;-1:-1:-1;;;;;25356:30:1;;25353:50;;;25399:1;25396;25389:12;25353:50;25422;25464:7;25455:6;25444:9;25440:22;25422:50;:::i;:::-;25412:60;;;24812:666;;;;;;;:::o;25483:457::-;25561:6;25569;25622:2;25610:9;25601:7;25597:23;25593:32;25590:52;;;25638:1;25635;25628:12;25590:52;25677:9;25664:23;25696:31;25721:5;25696:31;:::i;:::-;25746:5;-1:-1:-1;25802:2:1;25787:18;;25774:32;-1:-1:-1;;;;;25818:30:1;;25815:50;;;25861:1;25858;25851:12;25945:267;26143:2;26128:18;;26155:51;26132:9;26188:6;26155:51;:::i;26217:773::-;26339:6;26347;26355;26363;26416:2;26404:9;26395:7;26391:23;26387:32;26384:52;;;26432:1;26429;26422:12;26384:52;26459:23;;-1:-1:-1;;;;;26531:14:1;;;26528:34;;;26558:1;26555;26548:12;26528:34;26597:70;26659:7;26650:6;26639:9;26635:22;26597:70;:::i;:::-;26686:8;;-1:-1:-1;26571:96:1;-1:-1:-1;26774:2:1;26759:18;;26746:32;;-1:-1:-1;26790:16:1;;;26787:36;;;26819:1;26816;26809:12;26787:36;;26858:72;26922:7;26911:8;26900:9;26896:24;26858:72;:::i;:::-;26217:773;;;;-1:-1:-1;26949:8:1;-1:-1:-1;;;;26217:773:1:o;26995:543::-;27083:6;27091;27144:2;27132:9;27123:7;27119:23;27115:32;27112:52;;;27160:1;27157;27150:12;27112:52;27187:23;;-1:-1:-1;;;;;27259:14:1;;;27256:34;;;27286:1;27283;27276:12;27256:34;27309:50;27351:7;27342:6;27331:9;27327:22;27309:50;:::i;:::-;27299:60;;27412:2;27401:9;27397:18;27384:32;27368:48;;27441:2;27431:8;27428:16;27425:36;;;27457:1;27454;27447:12;27425:36;;27480:52;27524:7;27513:8;27502:9;27498:24;27480:52;:::i;27543:388::-;27611:6;27619;27672:2;27660:9;27651:7;27647:23;27643:32;27640:52;;;27688:1;27685;27678:12;27640:52;27727:9;27714:23;27746:31;27771:5;27746:31;:::i;:::-;27796:5;-1:-1:-1;27853:2:1;27838:18;;27825:32;27866:33;27825:32;27866:33;:::i;27936:451::-;28011:6;28019;28072:2;28060:9;28051:7;28047:23;28043:32;28040:52;;;28088:1;28085;28078:12;28040:52;28115:23;;-1:-1:-1;;;;;28150:30:1;;28147:50;;;28193:1;28190;28183:12;28147:50;28216;28258:7;28249:6;28238:9;28234:22;28216:50;:::i;:::-;28206:60;;;28316:2;28305:9;28301:18;28288:32;28329:28;28351:5;28329:28;:::i;28392:355::-;28594:2;28576:21;;;28633:2;28613:18;;;28606:30;28672:33;28667:2;28652:18;;28645:61;28738:2;28723:18;;28392:355::o;28752:276::-;28883:3;28921:6;28915:13;28937:53;28983:6;28978:3;28971:4;28963:6;28959:17;28937:53;:::i;:::-;29006:16;;;;;28752:276;-1:-1:-1;;28752:276:1:o;29372:127::-;29433:10;29428:3;29424:20;29421:1;29414:31;29464:4;29461:1;29454:15;29488:4;29485:1;29478:15;29504:128;29544:3;29575:1;29571:6;29568:1;29565:13;29562:39;;;29581:18;;:::i;:::-;-1:-1:-1;29617:9:1;;29504:128::o;29978:327::-;30180:2;30162:21;;;30219:1;30199:18;;;30192:29;-1:-1:-1;;;30252:2:1;30237:18;;30230:34;30296:2;30281:18;;29978:327::o;30310:168::-;30350:7;30416:1;30412;30408:6;30404:14;30401:1;30398:21;30393:1;30386:9;30379:17;30375:45;30372:71;;;30423:18;;:::i;:::-;-1:-1:-1;30463:9:1;;30310:168::o;30483:282::-;-1:-1:-1;;;;;30683:32:1;;;;30665:51;;30747:2;30732:18;;30725:34;30653:2;30638:18;;30483:282::o;30770:380::-;30849:1;30845:12;;;;30892;;;30913:61;;30967:4;30959:6;30955:17;30945:27;;30913:61;31020:2;31012:6;31009:14;30989:18;30986:38;30983:161;;31066:10;31061:3;31057:20;31054:1;31047:31;31101:4;31098:1;31091:15;31129:4;31126:1;31119:15;30983:161;;30770:380;;;:::o;31155:127::-;31216:10;31211:3;31207:20;31204:1;31197:31;31247:4;31244:1;31237:15;31271:4;31268:1;31261:15;31287:135;31326:3;31347:17;;;31344:43;;31367:18;;:::i;:::-;-1:-1:-1;31414:1:1;31403:13;;31287:135::o;31427:335::-;31629:2;31611:21;;;31668:2;31648:18;;;31641:30;-1:-1:-1;;;31702:2:1;31687:18;;31680:41;31753:2;31738:18;;31427:335::o;32536:337::-;32738:2;32720:21;;;32777:2;32757:18;;;32750:30;-1:-1:-1;;;32811:2:1;32796:18;;32789:43;32864:2;32849:18;;32536:337::o;32878:331::-;33080:2;33062:21;;;33119:1;33099:18;;;33092:29;-1:-1:-1;;;33152:2:1;33137:18;;33130:38;33200:2;33185:18;;32878:331::o;34228:127::-;34289:10;34284:3;34280:20;34277:1;34270:31;34320:4;34317:1;34310:15;34344:4;34341:1;34334:15;34360:120;34400:1;34426;34416:35;;34431:18;;:::i;:::-;-1:-1:-1;34465:9:1;;34360:120::o;34485:184::-;34555:6;34608:2;34596:9;34587:7;34583:23;34579:32;34576:52;;;34624:1;34621;34614:12;34576:52;-1:-1:-1;34647:16:1;;34485:184;-1:-1:-1;34485:184:1:o;36174:142::-;36250:20;;36279:31;36250:20;36279:31;:::i;36321:1289::-;36487:6;36495;36503;36511;36519;36527;36535;36543;36551;36559;36567:7;36621:3;36609:9;36600:7;36596:23;36592:33;36589:53;;;36638:1;36635;36628:12;36589:53;-1:-1:-1;;;;;36694:23:1;;36691:31;-1:-1:-1;36688:51:1;;;36735:1;36732;36725:12;36688:51;36758:67;36817:7;36804:9;36791:23;36780:9;36776:39;36758:67;:::i;:::-;36748:77;;36874:2;36868;36857:9;36853:18;36840:32;36837:40;36834:60;;;36890:1;36887;36880:12;36834:60;36913:76;36981:7;36974:2;36963:9;36959:18;36946:32;36935:9;36931:48;36913:76;:::i;:::-;36903:86;;37038:2;37032;37021:9;37017:18;37004:32;37001:40;36998:60;;;37054:1;37051;37044:12;36998:60;;37077:76;37145:7;37138:2;37127:9;37123:18;37110:32;37099:9;37095:48;37077:76;:::i;:::-;37067:86;;37172:46;37214:2;37203:9;37199:18;37172:46;:::i;:::-;37162:56;;37237:36;37268:3;37257:9;37253:19;37237:36;:::i;:::-;37227:46;;37292:36;37323:3;37312:9;37308:19;37292:36;:::i;:::-;37282:46;;37347:36;37378:3;37367:9;37363:19;37347:36;:::i;:::-;37337:46;;37402:36;37433:3;37422:9;37418:19;37402:36;:::i;:::-;37392:46;;37457:36;37488:3;37477:9;37473:19;37457:36;:::i;:::-;37447:46;;37512:36;37543:3;37532:9;37528:19;37512:36;:::i;:::-;37502:46;;37568:36;37599:3;37588:9;37584:19;37568:36;:::i;:::-;37557:47;;36321:1289;;;;;;;;;;;;;;:::o;37615:340::-;37817:2;37799:21;;;37856:2;37836:18;;;37829:30;-1:-1:-1;;;37890:2:1;37875:18;;37868:46;37946:2;37931:18;;37615:340::o;37960:342::-;38162:2;38144:21;;;38201:2;38181:18;;;38174:30;-1:-1:-1;;;38235:2:1;38220:18;;38213:48;38293:2;38278:18;;37960:342::o;38653:617::-;38933:3;38971:6;38965:13;38987:53;39033:6;39028:3;39021:4;39013:6;39009:17;38987:53;:::i;:::-;-1:-1:-1;;;39062:16:1;;;39087:21;;;39133:13;;39155:65;39133:13;39207:1;39196:13;;39189:4;39177:17;;39155:65;:::i;:::-;39240:20;39262:1;39236:28;;38653:617;-1:-1:-1;;;;38653:617:1:o;39275:451::-;39507:3;39545:6;39539:13;39561:53;39607:6;39602:3;39595:4;39587:6;39583:17;39561:53;:::i;:::-;-1:-1:-1;;;39636:16:1;;39661:29;;;-1:-1:-1;39717:2:1;39706:14;;39275:451;-1:-1:-1;39275:451:1:o;40758:221::-;40797:4;40826:10;40886;;;;40856;;40908:12;;;40905:38;;;40923:18;;:::i;:::-;40960:13;;40758:221;-1:-1:-1;;;40758:221:1:o;40984:786::-;-1:-1:-1;;;41390:3:1;41383:38;41365:3;41450:6;41444:13;41466:62;41521:6;41516:2;41511:3;41507:12;41500:4;41492:6;41488:17;41466:62;:::i;:::-;-1:-1:-1;;;41587:2:1;41547:16;;;41579:11;;;41572:40;41637:13;;41659:63;41637:13;41708:2;41700:11;;41693:4;41681:17;;41659:63;:::i;:::-;41742:17;41761:2;41738:26;;40984:786;-1:-1:-1;;;;40984:786:1:o;42386:489::-;-1:-1:-1;;;;;42655:15:1;;;42637:34;;42707:15;;42702:2;42687:18;;42680:43;42754:2;42739:18;;42732:34;;;42802:3;42797:2;42782:18;;42775:31;;;42580:4;;42823:46;;42849:19;;42841:6;42823:46;:::i;:::-;42815:54;42386:489;-1:-1:-1;;;;;;42386:489:1:o;42880:249::-;42949:6;43002:2;42990:9;42981:7;42977:23;42973:32;42970:52;;;43018:1;43015;43008:12;42970:52;43050:9;43044:16;43069:30;43093:5;43069:30;:::i;43134:125::-;43174:4;43202:1;43199;43196:8;43193:34;;;43207:18;;:::i;:::-;-1:-1:-1;43244:9:1;;43134:125::o;43264:112::-;43296:1;43322;43312:35;;43327:18;;:::i;:::-;-1:-1:-1;43361:9:1;;43264:112::o;43381:407::-;43583:2;43565:21;;;43622:2;43602:18;;;43595:30;43661:34;43656:2;43641:18;;43634:62;-1:-1:-1;;;43727:2:1;43712:18;;43705:41;43778:3;43763:19;;43381:407::o;43793:136::-;43832:3;43860:5;43850:39;;43869:18;;:::i;:::-;-1:-1:-1;;;43905:18:1;;43793:136::o;44681:127::-;44742:10;44737:3;44733:20;44730:1;44723:31;44773:4;44770:1;44763:15;44797:4;44794:1;44787:15;46332:245;46399:6;46452:2;46440:9;46431:7;46427:23;46423:32;46420:52;;;46468:1;46465;46458:12;46420:52;46500:9;46494:16;46519:28;46541:5;46519:28;:::i;46993:127::-;47054:10;47049:3;47045:20;47042:1;47035:31;47085:4;47082:1;47075:15;47109:4;47106:1;47099:15

Swarm Source

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