Token wstETH MAI Vault

 

Overview ERC-721

Total Supply:
213 WSTEMVT

Holders:
201 addresses

Transfers:
-

 
Loading
[ Download CSV Export  ] 
Loading
[ Download CSV Export  ] 
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
stableQiVault

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at PolygonScan.com on 2023-03-01
*/

// Sources flattened with hardhat v2.12.2 https://hardhat.org

// File @openzeppelin/contracts/utils/[email protected]

// OpenZeppelin Contracts (last updated v4.8.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 functionCallWithValue(target, data, 0, "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");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or 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 {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // 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
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}


// File @openzeppelin/contracts/token/ERC721/[email protected]

// OpenZeppelin Contracts (last updated v4.6.0) (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 `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}


// File @openzeppelin/contracts/utils/[email protected]

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

pragma solidity ^0.8.0;

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

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


// File @openzeppelin/contracts/utils/introspection/[email protected]

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

pragma solidity ^0.8.0;

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


// File @openzeppelin/contracts/token/ERC721/[email protected]

// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * 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;

    /**
     * @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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * 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 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 the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

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


// File @openzeppelin/contracts/utils/math/[email protected]

// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

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

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

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

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

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}


// File @openzeppelin/contracts/utils/[email protected]

// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @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] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}


// File @openzeppelin/contracts/token/ERC721/extensions/[email protected]

// 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 IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

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

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


// File @openzeppelin/contracts/utils/introspection/[email protected]

// 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 ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}


// File @openzeppelin/contracts/token/ERC721/[email protected]

// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;







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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _ownerOf(tokenId);
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

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

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

        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 overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

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

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

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

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

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

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

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

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

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

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

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

        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
        require(!_exists(tokenId), "ERC721: token already minted");

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

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

        _afterTokenTransfer(address(0), to, tokenId, 1);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

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

        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
        owner = ERC721.ownerOf(tokenId);

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

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

        _afterTokenTransfer(owner, address(0), tokenId, 1);
    }

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

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

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

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

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

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

    /**
     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
     * - When `from` is zero, the tokens will be minted for `to`.
     * - When `to` is zero, ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256, /* firstTokenId */
        uint256 batchSize
    ) internal virtual {
        if (batchSize > 1) {
            if (from != address(0)) {
                _balances[from] -= batchSize;
            }
            if (to != address(0)) {
                _balances[to] += batchSize;
            }
        }
    }

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual {}
}


// File @openzeppelin/contracts/token/ERC721/extensions/[email protected]

// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;

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

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

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


// File @openzeppelin/contracts/token/ERC721/extensions/[email protected]

// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

    /**
     * @dev See {ERC721-_beforeTokenTransfer}.
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);

        if (batchSize > 1) {
            // Will only trigger during construction. Batch transferring (minting) is not available afterwards.
            revert("ERC721Enumerable: consecutive transfers not supported");
        }

        uint256 tokenId = firstTokenId;

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

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

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

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

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

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

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

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

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

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

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

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

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


// File contracts/token/ERC721/MyVaultV5.sol

// contracts/MyVaultNFT.sol
pragma solidity 0.8.11;



contract VaultNFTv5 is ERC721, ERC721Enumerable {

    bool public custom;

    string internal baseURI;

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

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

    constructor(string memory name, string memory symbol, string memory _baseURI)
        ERC721(name, symbol)
    {
        baseURI = _baseURI;
    }

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

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

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


// File contracts/interfaces/external/IPriceSourceAll.sol

pragma solidity 0.8.11;
interface IPriceSource {
    function latestRoundData() external view returns (uint256);
    function latestAnswer() external view returns (uint256);
    function decimals() external view returns (uint8);
}


// File @openzeppelin/contracts/token/ERC20/[email protected]

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

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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);

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


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}


// File @openzeppelin/contracts/token/ERC20/utils/[email protected]

// OpenZeppelin Contracts (last updated v4.8.0) (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));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @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 @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}


// File @openzeppelin/contracts/token/ERC20/[email protected]

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

pragma solidity ^0.8.0;



/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

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

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}


// File @openzeppelin/contracts/security/[email protected]

// OpenZeppelin Contracts (last updated v4.8.0) (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 ReentrancyGuard {
    // 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;

    constructor() {
        _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() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

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


// File contracts/fixedInterestVaults/fixedVault.sol

pragma solidity 0.8.11;




contract fixedVault is ReentrancyGuard, VaultNFTv5 {
    using SafeERC20 for ERC20;

    /// @dev Constants used across the contract.
    uint256 constant TEN_THOUSAND = 10000;
    uint256 constant ONE_YEAR = 31556952;
    uint256 constant THOUSAND = 1000;

    IPriceSource public ethPriceSource;

    uint256 public _minimumCollateralPercentage;

    uint256 public vaultCount;
    
    uint256 public closingFee;
    uint256 public openingFee;

    uint256 public minDebt;
    uint256 public maxDebt;

    uint256 constant public tokenPeg = 1e8; // $1

    uint256 public iR;

    mapping(uint256 => uint256) public vaultCollateral;
    mapping(uint256 => uint256) public accumulatedVaultDebt;

    mapping(uint256 => uint256) public lastInterest;
    mapping(uint256 => uint256) public promoter;

    uint256 public adminFee; // 10% of the earned interest
    uint256 public refFee; // 90% of the earned interest

    uint256 public debtRatio;
    uint256 public gainRatio;

    ERC20 public collateral;
    ERC20 public mai;

    uint256 public decimalDifferenceRaisedToTen;

    uint256 public priceSourceDecimals;
    uint256 public totalBorrowed;

    mapping(address => uint256) public maticDebt;
    uint256 public maiDebt;

    address public stabilityPool;
    address public adm;
    address public ref;
    address public router;
    uint8 public version = 8;

    event CreateVault(uint256 vaultID, address creator);
    event DestroyVault(uint256 vaultID);
    event DepositCollateral(uint256 vaultID, uint256 amount);
    event WithdrawCollateral(uint256 vaultID, uint256 amount);
    event BorrowToken(uint256 vaultID, uint256 amount);
    event PayBackToken(uint256 vaultID, uint256 amount, uint256 closingFee);
    event LiquidateVault(
        uint256 vaultID,
        address owner,
        address buyer,
        uint256 debtRepaid,
        uint256 collateralLiquidated,
        uint256 closingFee
    );
    event BoughtRiskyDebtVault(uint256 riskyVault, uint256 newVault, address riskyVaultBuyer, uint256 amountPaidtoBuy);

    constructor(
        address ethPriceSourceAddress,
        uint256 minimumCollateralPercentage,
        string memory name,
        string memory symbol,
        address _mai,
        address _collateral,
        string memory baseURI
    ) VaultNFTv5(name, symbol, baseURI) {
        
        require(ethPriceSourceAddress != address(0));
        require(minimumCollateralPercentage != 0);

        closingFee = 50; // 0.5%
        openingFee = 0; // 0.0% 

        ethPriceSource = IPriceSource(ethPriceSourceAddress);
        stabilityPool = address(0);
        
        maxDebt = 500000 ether; //Keeping maxDebt at 500K * 10^(18)


        debtRatio = 2; // 1/2, pay back 50%
        gainRatio = 1100; // /10 so 1.1

        _minimumCollateralPercentage = minimumCollateralPercentage;

        collateral = ERC20(_collateral);
        mai = ERC20(_mai);
        priceSourceDecimals = 8;
        
        /*
            This works only for collaterals with decimals < 18
        */
        decimalDifferenceRaisedToTen =
            10**(mai.decimals() - collateral.decimals());
        
        adm = msg.sender;
        ref = msg.sender;
    }

    modifier onlyVaultOwner(uint256 vaultID) {
        require(_exists(vaultID), "Vault does not exist");
        require(ownerOf(vaultID) == msg.sender, "Vault is not owned by you");
        _;
    }

    modifier onlyRouter() {
        require(
            router == address(0) || msg.sender == router,
            "must use router"
        );
        _;
    }

    modifier vaultExists(uint256 vaultID) {
        require(_exists(vaultID), "Vault does not exist");
        _;
    }

    modifier frontExists(uint256 vaultID) {
        require(_exists(vaultID), "front end vault does not exist");
        require(promoter[vaultID] <= TEN_THOUSAND && promoter[vaultID] > 0, "Front end not added");
        _;
    }

    /// @notice Return the current debt available to borrow.
    /// @dev checks the outstanding balance of the borrowable asset within the contract.
    /// @return available balance of borrowable asset.
    function getDebtCeiling() public view returns (uint256) {
        return mai.balanceOf(address(this));
    }

    /// @param vaultID is the token id of the vault being checked.
    /// @notice Returns true if a vault exists
    /// @dev the erc721 spec allows users to burn/destroy their nft
    /// @return boolean if the vault exists
    function exists(uint256 vaultID) external view returns (bool) {
        return _exists(vaultID);
    }

    /// @notice Returns the total value locked in the vault, based on the oracle price.
    /// @return uint256 total value locked in vault
    function getTotalValueLocked() external view returns (uint256) {
        return ( getEthPriceSource() * decimalDifferenceRaisedToTen * collateral.balanceOf(address(this)) ) ; //extra 1e8, to get fraction in ui
                // 1e8 * 1eDelta 
    }

    /// @notice Return the fee charged when repaying a vault.
    /// @return uint256 is the fee charged to a vault when repaying.
    function getClosingFee() external view returns (uint256) {
        return closingFee;
    }

    /// @notice Return the peg maintained by the vault.
    /// @return uint256 is the value with 8 decimals used to calculate borrowable debt.
    function getTokenPriceSource() public view returns (uint256) {
        return tokenPeg;
    }

    /// @notice Return the collateral value
    /// @return uint256 is the value retrieved from the oracle used
    /// to calculate the available borrowable amounts.
    function getEthPriceSource() public view returns (uint256) {
        return ethPriceSource.latestAnswer();
    }

    /// @param vaultID is the token id of the vault being checked.
    /// @notice Returns the debt owned by the vault and the interest accrued over time.
    /// @return uint256 fee earned in the time between updates
    /// @return uint256 debt owed by the vault for further calculation.
    function _vaultDebtAndFee(uint256 vaultID)
        internal
        view
        returns (uint256, uint256)
    {
        uint256 currentTime = block.timestamp;
        uint256 debt = accumulatedVaultDebt[vaultID];
        uint256 fee = 0;
        if (lastInterest[vaultID] != 0 && iR > 0) {
            uint256 timeDelta = currentTime - lastInterest[vaultID];

            uint256 feeAccrued = (((iR * debt) * timeDelta) / ONE_YEAR) / TEN_THOUSAND;
            fee = feeAccrued;
            debt = feeAccrued + debt;
        }
        return (fee, debt);
    }

    /// @param vaultID is the token id of the vault being checked.
    /// @notice Returns the debt owned by the vault without tracking the interest
    /// @return uint256 debt owed by the vault for further calculation.
    function vaultDebt(uint256 vaultID) public view returns (uint256) {
        (, uint256 debt) = _vaultDebtAndFee(vaultID);
        return debt;
    }

    /// @param vaultID is the token id of the vault being checked.
    /// @notice Adds the interest charged to the vault over the previous time called.
    /// @return uint256 latest vault debt
    function updateVaultDebt(uint256 vaultID) public returns (uint256) {
        (uint256 fee, uint256 debt) = _vaultDebtAndFee(vaultID);

        maiDebt = maiDebt + fee;

        totalBorrowed = totalBorrowed + fee;

        if(iR > 0) {
            lastInterest[vaultID] = block.timestamp;
        }

        // we can just update the current vault debt here instead
        accumulatedVaultDebt[vaultID] = debt;

        return debt;
    }

    /// @param _collateral is the amount of collateral tokens to be valued.
    /// @param _debt is the debt owed by the vault.
    /// @notice Returns collateral value and debt based on the oracle prices
    /// @return uint256 coolateral value * 100. used to calculate the CDR
    /// @return uint256 debt value. Uses token price source to derive.
    function calculateCollateralProperties(uint256 _collateral, uint256 _debt)
        private
        view
        returns (uint256, uint256)
    {
        require(getEthPriceSource() != 0);
        require(getTokenPriceSource() != 0);

        uint256 collateralValue = _collateral *
            getEthPriceSource() *
            decimalDifferenceRaisedToTen;

        require(collateralValue >= _collateral);

        uint256 debtValue = _debt * getTokenPriceSource();

        require(debtValue >= _debt);

        uint256 collateralValueTimes100 = collateralValue * 100;
        require(collateralValueTimes100 > collateralValue);

        return (collateralValueTimes100, debtValue);
    }

    
    /// @param _collateral is the amount of collateral tokens held by vault.
    /// @param debt is the debt owed by the vault.
    /// @notice Calculates if the CDR is valid before taking a further action with a user
    /// @return boolean describing if the new CDR is valid.
    function isValidCollateral(uint256 _collateral, uint256 debt)
        public
        view
        returns (bool)
    {
        (
            uint256 collateralValueTimes100,
            uint256 debtValue
        ) = calculateCollateralProperties(_collateral, debt);

        uint256 collateralPercentage = collateralValueTimes100 / debtValue;
        return collateralPercentage >= _minimumCollateralPercentage;
    }

    

    /// @param fee is the amount of basis points (BP) to charge
    /// @param amount is the total value to calculate the BPs from
    /// @param promoFee is the fee charged by the front end
    /// @notice Returns fee to charge based on the collateral amount
    /// @return uint256 fee to charge the collateral.
    /// @dev fee can be called on web app to compare charges.
    function calculateFee(
        uint256 fee,
        uint256 amount,
        uint256 promoFee
    ) public view returns (uint256) {
        uint256 _fee;
        if (promoFee>0) {
            _fee = ((amount * fee * getTokenPriceSource() * promoFee) /
                (getEthPriceSource() * TEN_THOUSAND * TEN_THOUSAND));
        } else {
            _fee = (amount * fee * getTokenPriceSource()) /
                (getEthPriceSource() * TEN_THOUSAND);
        }
        return _fee / decimalDifferenceRaisedToTen;
    }

    /// @notice Creates a new ERC721 Vault NFT
    /// @return uint256 the token id of the vault created.
    function createVault() public returns (uint256) {
        uint256 id = vaultCount;
        vaultCount = vaultCount + 1;
        require(vaultCount >= id);
        _mint(msg.sender, id);
        emit CreateVault(id, msg.sender);
        return id;
    }

    /// @notice Destroys an ERC721 Vault NFT
    /// @param vaultID the vault ID to destroy
    /// @dev vault must not have any debt owed to be able to be destroyed.
    function destroyVault(uint256 vaultID)
        external
        onlyVaultOwner(vaultID)
        nonReentrant
    {
        require(vaultDebt(vaultID) == 0, "Vault has outstanding debt");

        if (vaultCollateral[vaultID] != 0) {
            // withdraw leftover collateral
            collateral.safeTransfer(ownerOf(vaultID), vaultCollateral[vaultID]);
        }

        _burn(vaultID);

        delete vaultCollateral[vaultID];
        delete accumulatedVaultDebt[vaultID];
        delete lastInterest[vaultID];
        emit DestroyVault(vaultID);
    }

    /// @param vaultID is the token id of the vault being interacted with.
    /// @param amount is the amount of collateral to deposit from msg.sender
    /// @notice Adds collateral to a specific vault by token id
    /// @dev Any address can deposit into a vault
    function depositCollateral(uint256 vaultID, uint256 amount)
        external
        vaultExists(vaultID)
        onlyRouter
    {
        uint256 newCollateral = vaultCollateral[vaultID] + (amount);

        require(newCollateral >= vaultCollateral[vaultID]);

        vaultCollateral[vaultID] = newCollateral;

        collateral.safeTransferFrom(msg.sender, address(this), amount);

        emit DepositCollateral(vaultID, amount);
    }

    /// @param vaultID is the token id of the vault being interacted with.
    /// @param amount is the amount of collateral to withdraw
    /// @notice withdraws collateral to a specific vault by token id
    /// @dev If there is debt, then it can only withdraw up to the min CDR.
    function withdrawCollateral(uint256 vaultID, uint256 amount)
        external
        onlyVaultOwner(vaultID)
        nonReentrant
    {
        require(
            vaultCollateral[vaultID] >= amount,
            "Vault does not have enough collateral"
        );

        uint256 newCollateral = vaultCollateral[vaultID] - amount;
        uint256 debt = updateVaultDebt(vaultID);

        if (debt != 0) {
            require(
                isValidCollateral(newCollateral, debt),
                "Withdrawal would put vault below minimum collateral percentage"
            );
        }

        vaultCollateral[vaultID] = newCollateral;
        collateral.safeTransfer(msg.sender, amount);

        emit WithdrawCollateral(vaultID, amount);
    }

    /// @param vaultID is the token id of the vault being interacted with.
    /// @param amount is the amount of borrowable asset to borrow
    /// @notice borrows asset based on the collateral held and the price of the collateral.
    /// @dev Borrowing is limited by the CDR of the vault
    /// If there's opening fee, it will be charged here.
    function borrowToken(
        uint256 vaultID,
        uint256 amount,
        uint256 _front
    ) external 
    frontExists(_front) 
    onlyVaultOwner(vaultID) 
    nonReentrant
    {

        require(amount > 0, "Must borrow non-zero amount");
        require(
            amount <= getDebtCeiling(),
            "borrowToken: Cannot mint over available supply."
        );

        uint256 newDebt = updateVaultDebt(vaultID) + amount;

        require(newDebt<=maxDebt, "borrowToken: max loan cap reached.");

        require(newDebt > vaultDebt(vaultID));


        require(
            isValidCollateral(vaultCollateral[vaultID], newDebt),
            "Borrow would put vault below minimum collateral percentage"
        );

        require(
            ((vaultDebt(vaultID)) + amount) >= minDebt,
            "Vault debt can't be under minDebt"
        );

        accumulatedVaultDebt[vaultID] = newDebt;

        uint256 _openingFee = calculateFee(openingFee, newDebt, promoter[_front]);

        vaultCollateral[vaultID] = vaultCollateral[vaultID] - (_openingFee);
        vaultCollateral[_front] = vaultCollateral[_front] + (_openingFee);
        
        // mai
        mai.safeTransfer(msg.sender, amount);
        totalBorrowed = totalBorrowed + (amount);

        emit BorrowToken(vaultID, amount);
    }

    function paybackTokenAll(
        uint256 vaultID,
        uint256 deadline,
        uint256 _front
    ) external frontExists(_front) vaultExists(vaultID) onlyRouter {
        require(
            deadline >= block.timestamp,
            "paybackTokenAll: deadline expired."
        );

        uint256 _amount = updateVaultDebt(vaultID);
        payBackToken(vaultID, _amount, _front);
    }

    /// @param vaultID is the token id of the vault being interacted with.
    /// @param amount is the amount of borrowable asset to repay
    /// @param _front is the front end that will get the opening
    /// @notice payback asset to close loan.
    /// @dev If there is debt, then it can only withdraw up to the min CDR.
    function payBackToken(
        uint256 vaultID,
        uint256 amount,
        uint256 _front
    ) public frontExists(_front) vaultExists(vaultID) onlyRouter {
        require(mai.balanceOf(msg.sender) >= amount, "Token balance too low");

        uint256 vaultDebtNow = updateVaultDebt(vaultID);

        require(
            vaultDebtNow >= amount,
            "Vault debt less than amount to pay back"
        );

        require(
            ((vaultDebtNow) - amount) >= minDebt || amount == (vaultDebtNow),
            "Vault debt can't be under minDebt"
        );

        uint256 _closingFee = calculateFee(
            closingFee,
            amount,
            promoter[_front]
        );

        accumulatedVaultDebt[vaultID] = vaultDebtNow - amount;

        vaultCollateral[vaultID] = vaultCollateral[vaultID] - _closingFee;
        vaultCollateral[_front] = vaultCollateral[_front] + _closingFee;

        totalBorrowed = totalBorrowed - amount;

        //mai
        mai.safeTransferFrom(msg.sender, address(this), amount);
        
        emit PayBackToken(vaultID, amount, _closingFee);
    }

    /// @notice withdraws liquidator earnings.
    /// @dev reverts if there's no collateral to withdraw.
    function getPaid() external nonReentrant {
        require(maticDebt[msg.sender] != 0, "Don't have anything for you.");
        uint256 amount = maticDebt[msg.sender];
        maticDebt[msg.sender] = 0;
        collateral.safeTransfer(msg.sender, amount);
    }

    /// @param pay is address of the person to getPaid
    /// @notice withdraws liquidator earnings.
    /// @dev reverts if there's no collateral to withdraw.
    function getPaid(address pay) external nonReentrant {
        require(maticDebt[pay] != 0, "Don't have anything for you.");
        uint256 amount = maticDebt[pay];
        maticDebt[pay] = 0;
        collateral.safeTransfer(pay, amount);
    }

    /// @param vaultID is the token id of the vault being interacted with.
    /// @notice Calculates cost to liquidate a vault
    /// @dev Can be used to calculate balance required to liquidate a vault. 
    function checkCost(uint256 vaultID) public view returns (uint256) {
        uint256 vaultDebtNow = vaultDebt(vaultID);

        if (
            vaultCollateral[vaultID] == 0 ||
            vaultDebtNow == 0 ||
            !checkLiquidation(vaultID)
        ) {
            return 0;
        }

        (,
            uint256 debtValue
        ) = calculateCollateralProperties(
                vaultCollateral[vaultID],
                vaultDebtNow
            );

        if (debtValue == 0) {
            return 0;
        }

        debtValue = debtValue / (10**priceSourceDecimals);

        uint256 halfDebt = debtValue / debtRatio; //debtRatio (2)

        if (halfDebt <= minDebt) {
            halfDebt = debtValue;
        }

        return (halfDebt);
    }

    /// @param vaultID is the token id of the vault being interacted with.
    /// @notice Calculates collateral to extract when liquidating a vault
    /// @dev Can be used to calculate earnings from liquidating a vault. 
    function checkExtract(uint256 vaultID) public view returns (uint256) {
        if (vaultCollateral[vaultID] == 0 || !checkLiquidation(vaultID)) {
            return 0;
        }
        uint256 vaultDebtNow = vaultDebt(vaultID);

        (, uint256 debtValue) = calculateCollateralProperties(
            vaultCollateral[vaultID],
            vaultDebtNow
        );

        uint256 halfDebt = debtValue / debtRatio; //debtRatio (2)

        if (halfDebt == 0) {
            return 0;
        }
        if ((halfDebt) / (10**priceSourceDecimals) <= minDebt) {
            // full liquidation if under the min debt.
            return (debtValue * ( gainRatio)) / (THOUSAND) / (getEthPriceSource()) / decimalDifferenceRaisedToTen;
        } else {
            return (halfDebt * (gainRatio)) / THOUSAND / (getEthPriceSource()) / decimalDifferenceRaisedToTen;
        }
    }

    /// @param vaultID is the token id of the vault being interacted with.
    /// @notice Calculates the collateral percentage of a vault.
    function checkCollateralPercentage(uint256 vaultID)
        public
        view
        vaultExists(vaultID)
        returns (uint256)
    {
        uint256 vaultDebtNow = vaultDebt(vaultID);

        if (vaultCollateral[vaultID] == 0 || vaultDebtNow == 0) {
            return 0;
        }
        (
            uint256 collateralValueTimes100,
            uint256 debtValue
        ) = calculateCollateralProperties(
                vaultCollateral[vaultID],
                vaultDebtNow
            );

        return collateralValueTimes100 / (debtValue);
    }

    /// @param vaultID is the token id of the vault being interacted with.
    /// @notice Calculates if a vault is liquidatable.
    /// @return bool if vault is liquidatable or not.
    function checkLiquidation(uint256 vaultID)
        public
        view
        vaultExists(vaultID)
        returns (bool)
    {
        uint256 vaultDebtNow = vaultDebt(vaultID);

        if (vaultCollateral[vaultID] == 0 || vaultDebtNow == 0) {
            return false;
        }

        (
            uint256 collateralValueTimes100,
            uint256 debtValue
        ) = calculateCollateralProperties(
                vaultCollateral[vaultID],
                vaultDebtNow
            );

        uint256 collateralPercentage = collateralValueTimes100 / (debtValue);
        if (collateralPercentage < _minimumCollateralPercentage) {
            return true;
        } else {
            return false;
        }
    }

    /// @param vaultID is the token id of the vault being interacted with.
    /// @notice Calculates if a vault is risky and can be bought.
    /// @return bool if vault is risky or not.
    function checkRiskyVault(uint256 vaultID) public view vaultExists(vaultID) returns (bool) {

        uint256 vaultDebtNow = vaultDebt(vaultID);

        if (vaultCollateral[vaultID] == 0 || vaultDebtNow == 0) {
            return false;
        }

        (
            uint256 collateralValueTimes100,
            uint256 debtValue
        ) = calculateCollateralProperties(
                vaultCollateral[vaultID],
                vaultDebtNow
            );

        uint256 collateralPercentage = collateralValueTimes100 / (debtValue);

        if ((collateralPercentage*10) <= gainRatio) {
            return true;
        } else {
            return false;
        }
    }


    /// @param vaultID is the token id of the vault being interacted with.
    /// @notice Pays back the part of the debt owed by the vault and removes a 
    /// comparable amount of collateral plus bonus
    /// @dev if vault CDR is under the bonus ratio,
    /// then it will only be able to be bought through buy risky.
    /// Amount to pay back is based on debtRatio variable.
    function liquidateVault(uint256 vaultID, uint256 _front)
        external
        frontExists(_front)
        vaultExists(vaultID)
    {
        require(
            stabilityPool == address(0) || msg.sender == stabilityPool,
            "liquidation is disabled for public"
        );

        uint256 vaultDebtNow = updateVaultDebt(vaultID);
        (
            uint256 collateralValueTimes100,
            uint256 debtValue
        ) = calculateCollateralProperties(
                vaultCollateral[vaultID],
                vaultDebtNow
            );
        require(vaultDebtNow != 0, "Vault debt is 0");

        uint256 collateralPercentage = collateralValueTimes100 / (debtValue);

        require(
            collateralPercentage < _minimumCollateralPercentage,
            "Vault is not below minimum collateral percentage"
        );

        require(collateralPercentage * 10 > gainRatio , "Vault is not above gain ratio");

        debtValue = debtValue / (10**priceSourceDecimals);

        uint256 halfDebt = debtValue / (debtRatio); //debtRatio (2)

        if (halfDebt <= minDebt) {
            halfDebt = debtValue;
        }

        require(
            mai.balanceOf(msg.sender) >= halfDebt,
            "Token balance too low to pay off outstanding debt"
        );

        totalBorrowed = totalBorrowed - (halfDebt);

        uint256 maticExtract = checkExtract(vaultID);

        accumulatedVaultDebt[vaultID] = vaultDebtNow - (halfDebt); // we paid back half of its debt.

        uint256 _closingFee = calculateFee(closingFee, halfDebt, promoter[_front]);
        vaultCollateral[vaultID] = vaultCollateral[vaultID] - (_closingFee);
        vaultCollateral[_front] = vaultCollateral[_front] + (_closingFee);

        
        // deduct the amount from the vault's collateral
        vaultCollateral[vaultID] = vaultCollateral[vaultID] - (maticExtract);

        // let liquidator take the collateral
        maticDebt[msg.sender] = maticDebt[msg.sender] + (maticExtract);

        //mai
        mai.safeTransferFrom(msg.sender, address(this), halfDebt);

        emit LiquidateVault(
            vaultID,
            ownerOf(vaultID),
            msg.sender,
            halfDebt,
            maticExtract,
            _closingFee
        );
    }

    /// @param vaultID is the token id of the vault being interacted with.
    /// @notice Pays back the debt owed to bring it back to min CDR. 
    /// And transfers ownership of it to the liquidator with a new vault
    /// @return uint256 new vault created with the debt and collateral.
    /// @dev this function can only be called if vault CDR is under the bonus ratio.
    /// address who calls it will now own the debt and the collateral.
    function buyRiskDebtVault(uint256 vaultID) external vaultExists(vaultID) nonReentrant returns(uint256) {
        require(
            stabilityPool == address(0) || msg.sender == stabilityPool,
            "buy risky is disabled for public"
        );        

        uint256 vaultDebtNow = updateVaultDebt(vaultID);

        require(vaultDebtNow != 0, "Vault debt is 0");

        (
            uint256 collateralValueTimes100,
            uint256 debtValue
        ) = calculateCollateralProperties(
                vaultCollateral[vaultID],
                vaultDebtNow
            );

        uint256 collateralPercentage = collateralValueTimes100 / (debtValue);
        require(
            (collateralPercentage*10) <= gainRatio,
            "Vault is not below risky collateral percentage"
        );

        uint256 maiDebtTobePaid = (debtValue / (10**priceSourceDecimals)) - 
                                    (collateralValueTimes100 / 
                                    ( _minimumCollateralPercentage * (10**priceSourceDecimals)));

        //have enough MAI to bring vault to X CDR (presumably min)
        require(mai.balanceOf(msg.sender) >= maiDebtTobePaid, "Not enough mai to buy the risky vault");
        //mai
        mai.safeTransferFrom(msg.sender, address(this), maiDebtTobePaid);
        totalBorrowed = totalBorrowed - (maiDebtTobePaid);
        // newVault for msg.sender
        uint256 newVault = createVault();
        // updating vault collateral and debt details for the transfer of risky vault
        vaultCollateral[newVault] = vaultCollateral[vaultID];
        accumulatedVaultDebt[newVault] = vaultDebtNow - maiDebtTobePaid;
        lastInterest[newVault] = block.timestamp;
        // resetting the vaultID vault info
        delete vaultCollateral[vaultID];
        delete accumulatedVaultDebt[vaultID];
        // lastInterest of vaultID would be block.timestamp, not reseting its timestamp
        emit BoughtRiskyDebtVault(vaultID, newVault, msg.sender, maiDebtTobePaid);
        return newVault;

    }
}


// File @openzeppelin/contracts/access/[email protected]

// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

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

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

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

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

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

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


// File contracts/fixedInterestVaults/fixedQiVault.sol

pragma solidity 0.8.11;


/// @title Fixed Interest Vault
/// @notice Single collateral lending manager with fixed rate interest.
contract stableQiVault is fixedVault, Ownable {

    /// @dev Used to restrain the fee. Can only be up to 5% of the amount.
    uint256 constant FEE_MAX = 500;
    
    string private oracleType;
    
    constructor(
        address ethPriceSourceAddress,
        uint256 minimumCollateralPercentage,
        string memory name,
        string memory symbol,
        address _mai,
        address _collateral,
        string memory baseURI
    )
        fixedVault(
            ethPriceSourceAddress,
            minimumCollateralPercentage,
            name,
            symbol,
            _mai,
            _collateral,
            baseURI
        )
    {
        createVault();
        addFrontEnd(0);
    }

    event UpdatedClosingFee(uint256 newFee);
    event UpdatedOpeningFee(uint256 newFee);
    event WithdrawInterest(uint256 earned);
    event UpdatedMinDebt(uint256 newMinDebt);
    event UpdatedMaxDebt(uint256 newMaxDebt);
    event UpdatedDebtRatio(uint256 _debtRatio);
    event UpdatedGainRatio(uint256 _gainRatio);
    event UpdatedEthPriceSource(address _ethPriceSourceAddress);
    
    event AddedFrontEnd(uint256 promoter);
    event RemovedFrontEnd(uint256 promoter);
    event UpdatedFrontEnd(uint256 promoter, uint256 newFee);

    event UpdatedFees(uint256 _adminFee, uint256 _refFee);

    event UpdatedMinCollateralRatio(uint256 newMinCollateralRatio);
    event UpdatedStabilityPool(address pool);
    event UpdatedInterestRate(uint256 interestRate);
    event BurnedToken(uint256 amount);
    event UpdatedTokenURI(string uri);

    event UpdatedAdmin(address newAdmin);
    event UpdatedRef(address newRef);
    event UpdatedOracleName(string oracle);

    event UpdatedRouter(address router);
    event UpdatedCustomURI(bool custom);

    modifier onlyOperators() {
        require(ref == msg.sender || adm == msg.sender || owner() == msg.sender, "Needs to be called by operators");
        _;
    }

    modifier onlyAdmin() {
        require(adm == msg.sender, "Needs to be called by admin");
        _;
    }

    /// @param _oracle name of the oracle used by the contract
    /// @notice sets the oracle name used by the contract. for visual purposes.
    function updateOracleName(string memory _oracle) external onlyOwner {
        oracleType = _oracle;
        emit UpdatedOracleName(_oracle);
    }

    /// @param _gainRatio sets the bonus earned from a liquidator
    /// @notice implements a setter for the bonus earned by a liquidator
    /// @dev fails if the bonus is less than 1
    function setGainRatio(uint256 _gainRatio) external onlyOwner {
        require(_gainRatio >= 1000, "gainRatio cannot be less than or equal to 1000");
        gainRatio = _gainRatio;
        emit UpdatedGainRatio(gainRatio);
    }

    /// @param _debtRatio sets the ratio of debt paid back by a liquidator
    /// @notice sets the ratio of the debt to be paid back
    /// @dev it divides the debt. 1/debtRatio.
    function setDebtRatio(uint256 _debtRatio) external onlyOwner {
        require(_debtRatio != 0, "Debt Ratio cannot be 0");
        debtRatio = _debtRatio;
        emit UpdatedDebtRatio(debtRatio);
    }

        /// @param ethPriceSourceAddress is the address that provides the price of the collateral
    /// @notice sets the address used as oracle
    /// @dev Oracle price feed is used in here. Interface's available in the at /interfaces/IPriceSourceAll.sol
    function changeEthPriceSource(address ethPriceSourceAddress)
        external
        onlyOwner
    {
        require(ethPriceSourceAddress != address(0), "Ethpricesource cannot be zero address" );
        ethPriceSource = IPriceSource(ethPriceSourceAddress);
        emit UpdatedEthPriceSource(ethPriceSourceAddress);
    }

    /// @param _pool is the address that can execute liquidations
    /// @notice sets the address used as stability pool for liquidations
    /// @dev if not set to address(0) then _pool is the only address able to liquidate
    function setStabilityPool(address _pool) external onlyOwner {
        require(_pool != address(0), "StabilityPool cannot be zero address" );
        stabilityPool = _pool;
        emit UpdatedStabilityPool(stabilityPool);
    }

    /// @param _admin is the ratio earned by the address that maintains the market
    /// @param _ref is the ratio earned by the address that provides the borrowable asset
    /// @notice sets the interest rate split between the admin and ref
    /// @dev if not set to address(0) then _pool is the only address able to liquidate
    function setFees(uint256 _admin, uint256 _ref) external onlyOwner {
        require((_admin+_ref)==TEN_THOUSAND, "setFees: must equal 10000.");
        adminFee=_admin;
        refFee=_ref;
        emit UpdatedFees(adminFee, refFee);
    }

    /// @param minimumCollateralPercentage is the CDR that limits the amount borrowed
    /// @notice sets the CDR
    /// @dev only callable by owner of the contract
    function setMinCollateralRatio(uint256 minimumCollateralPercentage)
        external
        onlyOwner
    {
        _minimumCollateralPercentage = minimumCollateralPercentage;
        emit UpdatedMinCollateralRatio(_minimumCollateralPercentage);
    }

    /// @param _minDebt is minimum debt able to be borrowed by a vault.
    /// @notice sets the minimum debt.
    /// @dev dust protection
    function setMinDebt(uint256 _minDebt)
        external
        onlyOwner
    {
        require(_minDebt >=0, "setMinDebt: must be over 0.");
        minDebt = _minDebt;
        emit UpdatedMinDebt(minDebt);
    }

    /// @param _maxDebt is maximum debt able to be borrowed by a vault.
    /// @notice sets the maximum debt.
    /// @dev whale and liquidity protection.
    function setMaxDebt(uint256 _maxDebt)
        external
        onlyOwner
    {
        require(_maxDebt >=0, "setMaxDebt: must be over 0.");
        maxDebt = _maxDebt;
        emit UpdatedMaxDebt(maxDebt);
    }

    /// @param _ref is the address that provides the borrowable asset
    /// @notice sets the address that earns interest for providing a borrowable asset
    /// @dev cannot be address(0)
    function setRef(address _ref) external onlyOwner {
        require(_ref != address(0), "Reference Address cannot be zero");
        ref = _ref;
        emit UpdatedRef(ref);
    }

    /// @param _adm is the ratio earned by the address that maintains the market
    /// @notice sets the address that earns interest for maintaining the market
    /// @dev cannot be address(0)
    function setAdmin(address _adm) external onlyOwner {
        require(_adm != address(0), "Admin Address cannot be zero");
        adm = _adm;
        emit UpdatedAdmin(adm);
    }

    /// @param _openingFee is the fee charged to a vault when borrowing.
    /// @notice sets opening fee.
    /// @dev can only be up to 5% (FEE_MAX) of the amount.
    function setOpeningFee(uint256 _openingFee) external onlyOwner {
        require(_openingFee >= 0 && _openingFee <= FEE_MAX, "setOpeningFee: cannot be more than 5%");
        openingFee = _openingFee;
        // emit event
        emit UpdatedOpeningFee(openingFee);
    }

    /// @param _closingFee is the fee charged to a vault when repaying.
    /// @notice sets closing fee.
    /// @dev can only be up to 5% (FEE_MAX) of the amount.
    function setClosingFee(uint256 _closingFee) external onlyOwner {
        require(_closingFee >= 0 && _closingFee <= FEE_MAX, "setClosingFee: cannot be more than 5%");
        closingFee = _closingFee;
        // emit event
        emit UpdatedClosingFee(closingFee);
    }

    /// @param _promoter is a front end for the contract
    /// @notice adds a front end to earn opening/closing fees from borrowing/repaying.
    /// @dev can only be up to 5% (FEE_MAX) of the amount.
    function addFrontEnd(uint256 _promoter) public onlyOwner {
        require(_exists(_promoter), "addFrontEnd: Vault does not exist");    
        require(promoter[_promoter] == 0, "addFrontEnd: already added");
        promoter[_promoter] = TEN_THOUSAND;
        emit AddedFrontEnd(_promoter);
    }

    /// @param _promoter is a front end for the contract
    /// @param cashback is the amount of fee not taken from a user.
    /// @notice updates the cashback variable for a given front end
    /// @dev can only be updated by the front end vault's owner
    function updateFrontEnd(uint256 _promoter, uint256 cashback) external frontExists(_promoter) onlyVaultOwner(_promoter) {
        require(cashback > 0 && cashback <= TEN_THOUSAND, "updateFrontEnd: cannot be 0");
        promoter[_promoter] = cashback;
        emit UpdatedFrontEnd(_promoter, cashback);
    }

    /// @param _promoter is a front end for the contract
    /// @notice removes the ability for a front end to earn fees
    function removeFrontEnd(uint256 _promoter) external frontExists(_promoter) onlyOwner {
        require(_exists(_promoter), "removeFrontEnd: Vault does not exist");
        require(promoter[_promoter] > 0, "removeFrontEnd: not a front end");
        promoter[_promoter] = 0;
        emit RemovedFrontEnd(_promoter);
    }

    /// @notice withdraws earned interest by vault.
    function withdrawInterest() external onlyOperators nonReentrant {

        uint256 adm_fee = maiDebt*adminFee / TEN_THOUSAND;

        // Transfer
        mai.transfer(ref, (maiDebt-adm_fee) ); // cheaper and equivalent.
        mai.transfer(adm, adm_fee);
        emit WithdrawInterest(maiDebt);
        maiDebt = 0;
    }

    /// @param _iR is the fixed interest charged by a vault
    /// @notice sets the interest charged by a vault.
    function setInterestRate(uint256 _iR) external onlyOwner {
        iR = _iR;
        emit UpdatedInterestRate(iR);
    }

    /// @param amountToken is the amount of borrowable asset that is removed from the debt ceiling.
    /// @notice removes debt ceiling from the vault.
    /// @dev returns the asset to the owner so it can be redeployed at a later time.
    function burn(uint256 amountToken) external onlyAdmin {
        // Burn
        require(amountToken <= mai.balanceOf(address(this)), "burn: Balance not enough");
        mai.transfer(ref, amountToken);
        emit BurnedToken(amountToken);
    }

    /// @param _baseURI is the url for the nft metadata
    /// @notice updates the metadata
    /// @dev it currently uses an ipfs json
    function setTokenURI(string calldata _baseURI) external onlyOwner {
        baseURI = _baseURI;
        emit UpdatedTokenURI(baseURI);
    }

    function setRouter(address _router) external onlyOwner {
        router=_router;
        emit UpdatedRouter(router);
    }

    function setCustomURI(bool _custom) external onlyOwner {
        custom=_custom;
        emit UpdatedCustomURI(custom);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"ethPriceSourceAddress","type":"address"},{"internalType":"uint256","name":"minimumCollateralPercentage","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"_mai","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"string","name":"baseURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"promoter","type":"uint256"}],"name":"AddedFrontEnd","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BorrowToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"riskyVault","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newVault","type":"uint256"},{"indexed":false,"internalType":"address","name":"riskyVaultBuyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountPaidtoBuy","type":"uint256"}],"name":"BoughtRiskyDebtVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BurnedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultID","type":"uint256"},{"indexed":false,"internalType":"address","name":"creator","type":"address"}],"name":"CreateVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"DestroyVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultID","type":"uint256"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"debtRepaid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralLiquidated","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"closingFee","type":"uint256"}],"name":"LiquidateVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"closingFee","type":"uint256"}],"name":"PayBackToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"promoter","type":"uint256"}],"name":"RemovedFrontEnd","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"UpdatedAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"UpdatedClosingFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"custom","type":"bool"}],"name":"UpdatedCustomURI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_debtRatio","type":"uint256"}],"name":"UpdatedDebtRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_ethPriceSourceAddress","type":"address"}],"name":"UpdatedEthPriceSource","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_adminFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_refFee","type":"uint256"}],"name":"UpdatedFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"promoter","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"UpdatedFrontEnd","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_gainRatio","type":"uint256"}],"name":"UpdatedGainRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"interestRate","type":"uint256"}],"name":"UpdatedInterestRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxDebt","type":"uint256"}],"name":"UpdatedMaxDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMinCollateralRatio","type":"uint256"}],"name":"UpdatedMinCollateralRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMinDebt","type":"uint256"}],"name":"UpdatedMinDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"UpdatedOpeningFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"oracle","type":"string"}],"name":"UpdatedOracleName","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newRef","type":"address"}],"name":"UpdatedRef","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"router","type":"address"}],"name":"UpdatedRouter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"UpdatedStabilityPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"UpdatedTokenURI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"earned","type":"uint256"}],"name":"WithdrawInterest","type":"event"},{"inputs":[],"name":"_minimumCollateralPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"accumulatedVaultDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_promoter","type":"uint256"}],"name":"addFrontEnd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adm","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"_front","type":"uint256"}],"name":"borrowToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"buyRiskDebtVault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"promoFee","type":"uint256"}],"name":"calculateFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"ethPriceSourceAddress","type":"address"}],"name":"changeEthPriceSource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"checkCollateralPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"checkCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"checkExtract","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"checkLiquidation","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"checkRiskyVault","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createVault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"custom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalDifferenceRaisedToTen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"destroyVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ethPriceSource","outputs":[{"internalType":"contract IPriceSource","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gainRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getClosingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDebtCeiling","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEthPriceSource","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pay","type":"address"}],"name":"getPaid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getPaid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getTokenPriceSource","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalValueLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"iR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateral","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"}],"name":"isValidCollateral","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastInterest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"},{"internalType":"uint256","name":"_front","type":"uint256"}],"name":"liquidateVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mai","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maiDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maticDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"_front","type":"uint256"}],"name":"payBackToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"_front","type":"uint256"}],"name":"paybackTokenAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"priceSourceDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"promoter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ref","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_promoter","type":"uint256"}],"name":"removeFrontEnd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"_adm","type":"address"}],"name":"setAdmin","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":"uint256","name":"_closingFee","type":"uint256"}],"name":"setClosingFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_custom","type":"bool"}],"name":"setCustomURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_debtRatio","type":"uint256"}],"name":"setDebtRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_admin","type":"uint256"},{"internalType":"uint256","name":"_ref","type":"uint256"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gainRatio","type":"uint256"}],"name":"setGainRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_iR","type":"uint256"}],"name":"setInterestRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxDebt","type":"uint256"}],"name":"setMaxDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minimumCollateralPercentage","type":"uint256"}],"name":"setMinCollateralRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minDebt","type":"uint256"}],"name":"setMinDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_openingFee","type":"uint256"}],"name":"setOpeningFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ref","type":"address"}],"name":"setRef","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"setStabilityPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stabilityPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenPeg","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBorrowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_promoter","type":"uint256"},{"internalType":"uint256","name":"cashback","type":"uint256"}],"name":"updateFrontEnd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_oracle","type":"string"}],"name":"updateOracleName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"updateVaultDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vaultCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"}],"name":"vaultDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawInterest","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526027805460ff60a01b1916600160a31b1790553480156200002457600080fd5b506040516200694c3803806200694c833981016040819052620000479162000c65565b868686868686868484828282600160008190555081600190805190602001906200007392919062000ad5565b5080516200008990600290602084019062000ad5565b50508151620000a19150600c90602084019062000ad5565b505050506001600160a01b038716620000b957600080fd5b85620000c457600080fd5b60326010556000601155600d80546001600160a01b03808a166001600160a01b03199283161790925560248054821690556969e10de76676d08000006013556002601b5561044c601c55600e889055601d80548584169083168117909155601e805493871693909216929092179055600860209081556040805163313ce56760e01b8152905163313ce567926004838101939192918290030181865afa15801562000173573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000199919062000d39565b601e60009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000213919062000d39565b6200021f919062000d7b565b6200022c90600a62000ea0565b601f55505060258054336001600160a01b03199182168117909255602680549091169091179055506200026f935062000269925062000293915050565b62000297565b62000279620002e9565b5062000286600062000357565b5050505050505062000f4f565b3390565b602880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600f54600090620002fc81600162000eb1565b600f8190558111156200030e57600080fd5b6200031a338262000484565b604080518281523360208201527f8b6c1d05c678fa59695e26465a85918ce0fc63a88f74af53d1daef8f0a9c7804910160405180910390a1919050565b6200036162000625565b6000818152600360205260409020546001600160a01b0316620003d55760405162461bcd60e51b815260206004820152602160248201527f61646446726f6e74456e643a205661756c7420646f6573206e6f7420657869736044820152601d60fa1b60648201526084015b60405180910390fd5b60008181526018602052604090205415620004335760405162461bcd60e51b815260206004820152601a60248201527f61646446726f6e74456e643a20616c72656164792061646465640000000000006044820152606401620003cc565b600081815260186020526040908190206127109055517f9d7c7013bbd38c45562efb3f7031f740c1f8b8886dbbf421142755ed68339f4c90620004799083815260200190565b60405180910390a150565b6001600160a01b038216620004dc5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401620003cc565b6000818152600360205260409020546001600160a01b031615620005435760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401620003cc565b6200055360008383600162000683565b6000818152600360205260409020546001600160a01b031615620005ba5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401620003cc565b6001600160a01b038216600081815260046020908152604080832080546001019055848352600390915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6028546001600160a01b03163314620006815760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620003cc565b565b6200069c84848484620006a260201b62003e4a1760201c565b50505050565b620006bb848484846200080660201b62003f831760201c565b6001811115620007345760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e736563757469766520747260448201527f616e7366657273206e6f7420737570706f7274656400000000000000000000006064820152608401620003cc565b816001600160a01b03851662000793576200078d81600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b620007b9565b836001600160a01b0316856001600160a01b031614620007b957620007b9858262000895565b6001600160a01b038416620007d957620007d38162000942565b620007ff565b846001600160a01b0316846001600160a01b031614620007ff57620007ff8482620009fc565b5050505050565b60018111156200069c576001600160a01b0384161562000850576001600160a01b038416600090815260046020526040812080548392906200084a90849062000ecc565b90915550505b6001600160a01b038316156200069c576001600160a01b038316600090815260046020526040812080548392906200088a90849062000eb1565b909155505050505050565b60006001620008af8462000a4d60201b620021951760201c565b620008bb919062000ecc565b6000838152600860205260409020549091508082146200090f576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b600954600090620009569060019062000ecc565b6000838152600a60205260408120546009805493945090928490811062000981576200098162000ee6565b906000526020600020015490508060098381548110620009a557620009a562000ee6565b6000918252602080832090910192909255828152600a90915260408082208490558582528120556009805480620009e057620009e062000efc565b6001900381819060005260206000200160009055905550505050565b600062000a148362000a4d60201b620021951760201c565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b60006001600160a01b03821662000ab95760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401620003cc565b506001600160a01b031660009081526004602052604090205490565b82805462000ae39062000f12565b90600052602060002090601f01602090048101928262000b07576000855562000b52565b82601f1062000b2257805160ff191683800117855562000b52565b8280016001018555821562000b52579182015b8281111562000b5257825182559160200191906001019062000b35565b5062000b6092915062000b64565b5090565b5b8082111562000b60576000815560010162000b65565b80516001600160a01b038116811462000b9357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011262000bc057600080fd5b81516001600160401b038082111562000bdd5762000bdd62000b98565b604051601f8301601f19908116603f0116810190828211818310171562000c085762000c0862000b98565b8160405283815260209250868385880101111562000c2557600080fd5b600091505b8382101562000c49578582018301518183018401529082019062000c2a565b8382111562000c5b5760008385830101525b9695505050505050565b600080600080600080600060e0888a03121562000c8157600080fd5b62000c8c8862000b7b565b602089015160408a015191985096506001600160401b038082111562000cb157600080fd5b62000cbf8b838c0162000bae565b965060608a015191508082111562000cd657600080fd5b62000ce48b838c0162000bae565b955062000cf460808b0162000b7b565b945062000d0460a08b0162000b7b565b935060c08a015191508082111562000d1b57600080fd5b5062000d2a8a828b0162000bae565b91505092959891949750929550565b60006020828403121562000d4c57600080fd5b815160ff8116811462000d5e57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff84168082101562000d985762000d9862000d65565b90039392505050565b600181815b8085111562000de257816000190482111562000dc65762000dc662000d65565b8085161562000dd457918102915b93841c939080029062000da6565b509250929050565b60008262000dfb5750600162000e9a565b8162000e0a5750600062000e9a565b816001811462000e23576002811462000e2e5762000e4e565b600191505062000e9a565b60ff84111562000e425762000e4262000d65565b50506001821b62000e9a565b5060208310610133831016604e8410600b841016171562000e73575081810a62000e9a565b62000e7f838362000da1565b806000190482111562000e965762000e9662000d65565b0290505b92915050565b600062000d5e60ff84168362000dea565b6000821982111562000ec75762000ec762000d65565b500190565b60008282101562000ee15762000ee162000d65565b500390565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b600181811c9082168062000f2757607f821691505b6020821081141562000f4957634e487b7160e01b600052602260045260246000fd5b50919050565b6159ed8062000f5f6000396000f3fe608060405234801561001057600080fd5b506004361061054a5760003560e01c806386375994116102ca578063c71abb321161018d578063d8dfeb45116100f4578063ec2e0ab3116100ad578063f1c91fa611610087578063f1c91fa614610bdf578063f2fde38b14610be8578063f887ea4014610bfb578063ffc73da714610c0e57600080fd5b8063ec2e0ab314610bba578063ece1373214610bc3578063f17336d714610bd657600080fd5b8063d8dfeb4514610b29578063df98784614610b3c578063e0df5b6f14610b4f578063e5f4dc9214610b62578063e985e9c514610b6b578063eb6a887d14610ba757600080fd5b8063cf41d6f811610146578063cf41d6f814610ab2578063cf5f0f3c14610aba578063d0064c0014610acd578063d310f49b14610ad6578063d4a9b2c514610ae9578063d73464cc14610b0957600080fd5b8063c71abb3214610a65578063c87b56dd14610a6e578063cc02ce2214610a81578063cd44db1b14610a94578063cdfedd6314610a9e578063cea55f5714610aa957600080fd5b8063a22cb46511610231578063b26025aa116101ea578063b26025aa14610a04578063b3229a6314610a0c578063b86f6aef14610a1f578063b88d4fde14610a32578063c0d7865514610a45578063c231aa3014610a5857600080fd5b8063a22cb465146109a4578063a57ff503146109b7578063a5e98837146109c0578063a7c6a100146109c8578063a9c904b5146109d1578063b165ff0b146109e457600080fd5b806395d89b411161028357806395d89b411461094557806397a41b8e1461094d57806397ff37b91461096057806398c3f2db1461098057806398d721e014610988578063a0be06f91461099b57600080fd5b806386375994146108e05780638da5cb5b146108f35780639035e4cb1461090457806393ee476a1461091757806394cd4ba71461092a578063952cc86a1461093257600080fd5b806342966c68116104125780636234dc2111610379578063704b6c0211610332578063704b6c021461088357806370a0823114610896578063715018a6146108a9578063728bbbb5146108b1578063767a7b05146108ba57806385e290a3146108cd57600080fd5b80636234dc21146108115780636352211e1461082457806363b8817c146108375780636526941b1461084a578063687e8c171461085d5780636bc855cc1461087057600080fd5b806354fd4d50116103cb57806354fd4d501461079757806356572ac0146107bd578063570b2b84146107d05780635d12928b146107e35780635f84f302146107eb5780635ff09ac2146107fe57600080fd5b806342966c681461072f57806342f371c6146107425780634c19386c146107555780634f558e791461075e5780634f6ccce7146107715780635357b9891461078457600080fd5b806321a78f68116104b65780633128ef271161046f5780633128ef27146106bd578063379394d0146106d057806338536275146106e35780633db99177146106f6578063408038541461070957806342842e0e1461071c57600080fd5b806321a78f681461065257806323b872dd14610665578063241a545a146106785780632df87573146106815780632f745c59146106a1578063311f392a146106b457600080fd5b8063081812fc11610508578063081812fc146105e7578063095ea7b3146105fa5780630b78f9c01461060d57806311b4a8321461062057806318160ddd146106415780631c883e7b1461064957600080fd5b806263750c1461054f57806301ffc9a714610559578063048c661d1461058157806304d7aef2146105ac57806306fdde03146105bf57806307960532146105d4575b600080fd5b610557610c21565b005b61056c61056736600461506c565b610e44565b60405190151581526020015b60405180910390f35b602454610594906001600160a01b031681565b6040516001600160a01b039091168152602001610578565b602554610594906001600160a01b031681565b6105c7610e55565b60405161057891906150e1565b6105576105e2366004615110565b610ee7565b6105946105f536600461512b565b610fa8565b610557610608366004615144565b610fcf565b61055761061b36600461516e565b6110e5565b61063361062e36600461512b565b61118f565b604051908152602001610578565b600954610633565b61063360105481565b602654610594906001600160a01b031681565b610557610673366004615190565b611241565b61063360145481565b61063361068f36600461512b565b60166020526000908152604090205481565b6106336106af366004615144565b611272565b610633601c5481565b6105576106cb3660046151cc565b611308565b6105576106de366004615206565b611625565b6105576106f136600461512b565b611674565b61055761070436600461512b565b6116b1565b61055761071736600461512b565b61174e565b61055761072a366004615190565b611856565b61055761073d36600461512b565b611871565b600d54610594906001600160a01b031681565b61063360215481565b61056c61076c36600461512b565b611a30565b61063361077f36600461512b565b611a3b565b6106336107923660046151cc565b611ace565b6027546107ab90600160a01b900460ff1681565b60405160ff9091168152602001610578565b6106336107cb36600461512b565b611b7d565b601e54610594906001600160a01b031681565b610633611c6e565b6105576107f936600461512b565b611cd7565b61055761080c36600461512b565b611d14565b61055761081f36600461512b565b611e8a565b61059461083236600461512b565b611ec7565b610557610845366004615110565b611f27565b61055761085836600461512b565b611fd1565b61056c61086b36600461516e565b61200e565b61055761087e366004615110565b61203d565b610557610891366004615110565b6120e9565b6106336108a4366004615110565b612195565b61055761221b565b61063360115481565b6105576108c836600461516e565b61222d565b6105576108db36600461512b565b61240f565b6105576108ee36600461512b565b612575565b6028546001600160a01b0316610594565b61063361091236600461512b565b612612565b61063361092536600461512b565b61299a565b610633612a01565b61055761094036600461516e565b612a73565b6105c7612f57565b61055761095b3660046151cc565b612f66565b61063361096e36600461512b565b60176020526000908152604090205481565b61063361332c565b610557610996366004615110565b613376565b61063360195481565b6105576109b2366004615223565b61342e565b610633601f5481565b601054610633565b610633600f5481565b6105576109df3660046152e6565b613439565b6106336109f2366004615110565b60226020526000908152604090205481565b610633613484565b61056c610a1a36600461512b565b613510565b61056c610a2d36600461512b565b6135ca565b610557610a4036600461532f565b61366d565b610557610a53366004615110565b6136a5565b600b5461056c9060ff1681565b61063360205481565b6105c7610a7c36600461512b565b6136fb565b610557610a8f36600461516e565b61376e565b6305f5e100610633565b6106336305f5e10081565b610633601b5481565b6105576138e3565b610557610ac83660046151cc565b61397f565b61063360135481565b610633610ae436600461512b565b613acd565b610633610af736600461512b565b60156020526000908152604090205481565b610633610b1736600461512b565b60186020526000908152604090205481565b601d54610594906001600160a01b031681565b610633610b4a36600461512b565b613ad9565b610557610b5d3660046153ab565b613b6b565b610633600e5481565b61056c610b7936600461541d565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b610557610bb536600461512b565b613bb0565b610633601a5481565b610557610bd136600461516e565b613c33565b61063360125481565b61063360235481565b610557610bf6366004615110565b613d2e565b602754610594906001600160a01b031681565b610557610c1c36600461512b565b613da4565b6026546001600160a01b0316331480610c4457506025546001600160a01b031633145b80610c68575033610c5d6028546001600160a01b031690565b6001600160a01b0316145b610cb95760405162461bcd60e51b815260206004820152601f60248201527f4e6565647320746f2062652063616c6c6564206279206f70657261746f72730060448201526064015b60405180910390fd5b610cc161400b565b6000612710601954602354610cd69190615466565b610ce09190615485565b601e546026546023549293506001600160a01b039182169263a9059cbb9290911690610d0d9085906154a7565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7c91906154be565b50601e5460255460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810184905291169063a9059cbb906044016020604051808303816000875af1158015610dd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df691906154be565b507fc73fb14682b9d51008c1faff296cc9b351c0597de5e25b4ffa158f47f8254e4c602354604051610e2a91815260200190565b60405180910390a1506000602355610e426001600055565b565b6000610e4f82614065565b92915050565b606060018054610e64906154db565b80601f0160208091040260200160405190810160405280929190818152602001828054610e90906154db565b8015610edd5780601f10610eb257610100808354040283529160200191610edd565b820191906000526020600020905b815481529060010190602001808311610ec057829003601f168201915b5050505050905090565b610eef61408a565b6001600160a01b038116610f535760405162461bcd60e51b815260206004820152602560248201527f4574687072696365736f757263652063616e6e6f74206265207a65726f206164604482015264647265737360d81b6064820152608401610cb0565b600d80546001600160a01b0319166001600160a01b0383169081179091556040519081527fc525e5fed1508c998d3f14bf52f933df1dd16dbf48e2944c426be721e268b755906020015b60405180910390a150565b6000610fb3826140e4565b506000908152600560205260409020546001600160a01b031690565b6000610fda82611ec7565b9050806001600160a01b0316836001600160a01b031614156110485760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610cb0565b336001600160a01b038216148061106457506110648133610b79565b6110d65760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610cb0565b6110e08383614134565b505050565b6110ed61408a565b6127106110fa8284615510565b146111475760405162461bcd60e51b815260206004820152601a60248201527f736574466565733a206d75737420657175616c2031303030302e0000000000006044820152606401610cb0565b6019829055601a81905560408051838152602081018390527f4d32f38862d5eb71edfefb7955873bd55920dc98159b6f53f8be62fbf0bebb4b91015b60405180910390a15050565b60008061119b83613acd565b60008481526015602052604090205490915015806111b7575080155b806111c857506111c6836135ca565b155b156111d65750600092915050565b6000838152601560205260408120546111ef90836141a2565b91505080611201575060009392505050565b60205461120f90600a61560c565b6112199082615485565b90506000601b548261122b9190615485565b905060125481116112395750805b949350505050565b61124b338261422b565b6112675760405162461bcd60e51b8152600401610cb090615618565b6110e08383836142a9565b600061127d83612195565b82106112df5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610cb0565b506001600160a01b03919091166000908152600760209081526040808320938352929052205490565b806113128161441a565b61132e5760405162461bcd60e51b8152600401610cb090615665565b6000818152601860205260409020546127101080159061135b575060008181526018602052604090205415155b6113775760405162461bcd60e51b8152600401610cb09061569c565b836113818161441a565b61139d5760405162461bcd60e51b8152600401610cb0906156c9565b6027546001600160a01b031615806113bf57506027546001600160a01b031633145b6113db5760405162461bcd60e51b8152600401610cb0906156f7565b601e546040516370a0823160e01b815233600482015285916001600160a01b0316906370a0823190602401602060405180830381865afa158015611423573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114479190615720565b101561148d5760405162461bcd60e51b8152602060048201526015602482015274546f6b656e2062616c616e636520746f6f206c6f7760581b6044820152606401610cb0565b60006114988661299a565b9050848110156114fa5760405162461bcd60e51b815260206004820152602760248201527f5661756c742064656274206c657373207468616e20616d6f756e7420746f20706044820152666179206261636b60c81b6064820152608401610cb0565b60125461150786836154a7565b10158061151357508085145b61152f5760405162461bcd60e51b8152600401610cb090615739565b601054600085815260186020526040812054909161154e918890611ace565b905061155a86836154a7565b6000888152601660209081526040808320939093556015905220546115809082906154a7565b6000888152601560205260408082209290925586815220546115a3908290615510565b6000868152601560205260409020556021546115c09087906154a7565b602155601e546115db906001600160a01b0316333089614437565b60408051888152602081018890529081018290527f31f96762af4051f367185773cc2f55bfb112a6c114b3407ded1f321a9eb199ac9060600160405180910390a150505050505050565b61162d61408a565b600b805460ff191682151590811790915560405160ff909116151581527f24d10a0e2bca30afd85b6fcbdae412b32757c23f2d09434b3748b5980c7133d590602001610f9d565b61167c61408a565b600e8190556040518181527fc0880963f3abc486dbb8b8f04ba4ce47c5b5cd3c59b6b7655f6011da0bf3365090602001610f9d565b6116b961408a565b6101f48111156117195760405162461bcd60e51b815260206004820152602560248201527f736574436c6f73696e674665653a2063616e6e6f74206265206d6f7265207468604482015264616e20352560d81b6064820152608401610cb0565b60108190556040518181527fc1b83121984ef8e824a0babc08fc162077c0716a4dc307121f306e6dfb13806c90602001610f9d565b61175661408a565b61175f8161441a565b6117b55760405162461bcd60e51b815260206004820152602160248201527f61646446726f6e74456e643a205661756c7420646f6573206e6f7420657869736044820152601d60fa1b6064820152608401610cb0565b600081815260186020526040902054156118115760405162461bcd60e51b815260206004820152601a60248201527f61646446726f6e74456e643a20616c72656164792061646465640000000000006044820152606401610cb0565b600081815260186020526040908190206127109055517f9d7c7013bbd38c45562efb3f7031f740c1f8b8886dbbf421142755ed68339f4c90610f9d9083815260200190565b6110e08383836040518060200160405280600081525061366d565b6025546001600160a01b031633146118cb5760405162461bcd60e51b815260206004820152601b60248201527f4e6565647320746f2062652063616c6c65642062792061646d696e00000000006044820152606401610cb0565b601e546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119379190615720565b8111156119865760405162461bcd60e51b815260206004820152601860248201527f6275726e3a2042616c616e6365206e6f7420656e6f75676800000000000000006044820152606401610cb0565b601e5460265460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810184905291169063a9059cbb906044016020604051808303816000875af11580156119db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ff91906154be565b506040518181527fb1f67ade07cda330ac167f4fcc4c01b94fdfc04d401cf85e487f0a5b8b98e75f90602001610f9d565b6000610e4f8261441a565b6000611a4660095490565b8210611aa95760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610cb0565b60098281548110611abc57611abc61577a565b90600052602060002001549050919050565b6000808215611b2c5761271080611ae361332c565b611aed9190615466565b611af79190615466565b836305f5e100611b078888615466565b611b119190615466565b611b1b9190615466565b611b259190615485565b9050611b67565b612710611b3761332c565b611b419190615466565b6305f5e100611b508787615466565b611b5a9190615466565b611b649190615485565b90505b601f54611b749082615485565b95945050505050565b6000818152601560205260408120541580611b9e5750611b9c826135ca565b155b15611bab57506000919050565b6000611bb683613acd565b60008481526015602052604081205491925090611bd390836141a2565b9150506000601b5482611be69190615485565b905080611bf857506000949350505050565b601254602054611c0990600a61560c565b611c139083615485565b11611c5257601f54611c2361332c565b6103e8601c5485611c349190615466565b611c3e9190615485565b611c489190615485565b611b749190615485565b601f54611c5d61332c565b6103e8601c5484611c349190615466565b600f54600090611c7f816001615510565b600f819055811115611c9057600080fd5b611c9a33826144a2565b604080518281523360208201527f8b6c1d05c678fa59695e26465a85918ce0fc63a88f74af53d1daef8f0a9c7804910160405180910390a1919050565b611cdf61408a565b60148190556040518181527f323264e3ca065ee856fe1b11204d8896a783bccf148380ac5d7362eb5c4c36a890602001610f9d565b80611d1e8161441a565b611d3a5760405162461bcd60e51b8152600401610cb090615665565b60008181526018602052604090205461271010801590611d67575060008181526018602052604090205415155b611d835760405162461bcd60e51b8152600401610cb09061569c565b611d8b61408a565b611d948261441a565b611dec5760405162461bcd60e51b8152602060048201526024808201527f72656d6f766546726f6e74456e643a205661756c7420646f6573206e6f7420656044820152631e1a5cdd60e21b6064820152608401610cb0565b600082815260186020526040902054611e475760405162461bcd60e51b815260206004820152601f60248201527f72656d6f766546726f6e74456e643a206e6f7420612066726f6e7420656e64006044820152606401610cb0565b60008281526018602052604080822091909155517f9b9f950fb3755096dbbe8b1519e73f7c6d1a0507f514fced444919530c00d719906111839084815260200190565b611e9261408a565b60128190556040518181527f4533506fbaba6b18743358b6e6fb9392e8cb21757487b68d232a01b140bbec0190602001610f9d565b6000818152600360205260408120546001600160a01b031680610e4f5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610cb0565b611f2f61400b565b6001600160a01b038116600090815260226020526040902054611f945760405162461bcd60e51b815260206004820152601c60248201527f446f6e2774206861766520616e797468696e6720666f7220796f752e000000006044820152606401610cb0565b6001600160a01b0380821660009081526022602052604081208054919055601d549091611fc39116838361461d565b50611fce6001600055565b50565b611fd961408a565b60138190556040518181527f1dd8f42ee4750a70f6662d1383372472422592497256d506437e35b3fa914d9b90602001610f9d565b600080600061201d85856141a2565b9092509050600061202e8284615485565b600e5411159695505050505050565b61204561408a565b6001600160a01b03811661209b5760405162461bcd60e51b815260206004820181905260248201527f5265666572656e636520416464726573732063616e6e6f74206265207a65726f6044820152606401610cb0565b602680546001600160a01b0319166001600160a01b0383169081179091556040519081527f8ed6553fa1e634b0152cd3539c572bee8c662e446820646d73a0e1b47776af9390602001610f9d565b6120f161408a565b6001600160a01b0381166121475760405162461bcd60e51b815260206004820152601c60248201527f41646d696e20416464726573732063616e6e6f74206265207a65726f000000006044820152606401610cb0565b602580546001600160a01b0319166001600160a01b0383169081179091556040519081527ffce52dd00c7849a7f2602c1f189745238d6a2db16fabf54376ce24cc2fa3d57f90602001610f9d565b60006001600160a01b0382166121ff5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610cb0565b506001600160a01b031660009081526004602052604090205490565b61222361408a565b610e42600061464d565b816122378161441a565b6122535760405162461bcd60e51b8152600401610cb0906156c9565b3361225d82611ec7565b6001600160a01b0316146122835760405162461bcd60e51b8152600401610cb090615790565b61228b61400b565b6000838152601560205260409020548211156122f75760405162461bcd60e51b815260206004820152602560248201527f5661756c7420646f6573206e6f74206861766520656e6f75676820636f6c6c616044820152641d195c985b60da1b6064820152608401610cb0565b6000838152601560205260408120546123119084906154a7565b9050600061231e8561299a565b905080156123a257612330828261200e565b6123a25760405162461bcd60e51b815260206004820152603e60248201527f5769746864726177616c20776f756c6420707574207661756c742062656c6f7760448201527f206d696e696d756d20636f6c6c61746572616c2070657263656e7461676500006064820152608401610cb0565b6000858152601560205260409020829055601d546123ca906001600160a01b0316338661461d565b60408051868152602081018690527f6c0ea3bea9dd66afa8f9d39d6eb93d833466190330813b42835efc650dca4cb9910160405180910390a150506110e06001600055565b806124198161441a565b6124355760405162461bcd60e51b8152600401610cb0906156c9565b3361243f82611ec7565b6001600160a01b0316146124655760405162461bcd60e51b8152600401610cb090615790565b61246d61400b565b61247682613acd565b156124c35760405162461bcd60e51b815260206004820152601a60248201527f5661756c7420686173206f75747374616e64696e6720646562740000000000006044820152606401610cb0565b60008281526015602052604090205415612505576125056124e383611ec7565b600084815260156020526040902054601d546001600160a01b0316919061461d565b61250e8261469f565b600082815260156020908152604080832083905560168252808320839055601782528083209290925590518381527f4fe08624ee65b341c38ab9693d216b909d4ddee1bc8d3fe0fea14026c361b465910160405180910390a16125716001600055565b5050565b61257d61408a565b6101f48111156125dd5760405162461bcd60e51b815260206004820152602560248201527f7365744f70656e696e674665653a2063616e6e6f74206265206d6f7265207468604482015264616e20352560d81b6064820152608401610cb0565b60118190556040518181527fc4ced91ca77dc4287a54d9bd9b15c69b3aba262e30eba7c93301c48606019c9490602001610f9d565b60008161261e8161441a565b61263a5760405162461bcd60e51b8152600401610cb0906156c9565b61264261400b565b6024546001600160a01b0316158061266457506024546001600160a01b031633145b6126b05760405162461bcd60e51b815260206004820181905260248201527f627579207269736b792069732064697361626c656420666f72207075626c69636044820152606401610cb0565b60006126bb8461299a565b9050806126fc5760405162461bcd60e51b815260206004820152600f60248201526e05661756c742064656274206973203608c1b6044820152606401610cb0565b600084815260156020526040812054819061271790846141a2565b909250905060006127288284615485565b601c5490915061273982600a615466565b111561279e5760405162461bcd60e51b815260206004820152602e60248201527f5661756c74206973206e6f742062656c6f77207269736b7920636f6c6c61746560448201526d72616c2070657263656e7461676560901b6064820152608401610cb0565b6000602054600a6127af919061560c565b600e546127bc9190615466565b6127c69085615485565b6020546127d490600a61560c565b6127de9085615485565b6127e891906154a7565b601e546040516370a0823160e01b815233600482015291925082916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612835573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128599190615720565b10156128b55760405162461bcd60e51b815260206004820152602560248201527f4e6f7420656e6f756768206d616920746f2062757920746865207269736b79206044820152641d985d5b1d60da1b6064820152608401610cb0565b601e546128cd906001600160a01b0316333084614437565b806021546128db91906154a7565b60215560006128e8611c6e565b60008a81526015602052604080822054838352912055905061290a82876154a7565b600082815260166020818152604080842094909455601781528383204290558c8352601581528383208390559081528282209190915581518b815290810183905233818301526060810184905290517fa4cf7276e26bb566de2c7540759e85736eb743807343fd27e6e679b20e8814419181900360800190a1965050505050506129946001600055565b50919050565b60008060006129a884614742565b91509150816023546129ba9190615510565b6023556021546129cb908390615510565b602155601454156129e85760008481526017602052604090204290555b6000938452601660205260409093208390555090919050565b601e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612a4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6e9190615720565b905090565b80612a7d8161441a565b612a995760405162461bcd60e51b8152600401610cb090615665565b60008181526018602052604090205461271010801590612ac6575060008181526018602052604090205415155b612ae25760405162461bcd60e51b8152600401610cb09061569c565b82612aec8161441a565b612b085760405162461bcd60e51b8152600401610cb0906156c9565b6024546001600160a01b03161580612b2a57506024546001600160a01b031633145b612b815760405162461bcd60e51b815260206004820152602260248201527f6c69717569646174696f6e2069732064697361626c656420666f72207075626c604482015261696360f01b6064820152608401610cb0565b6000612b8c8561299a565b600086815260156020526040812054919250908190612bab90846141a2565b915091508260001415612bf25760405162461bcd60e51b815260206004820152600f60248201526e05661756c742064656274206973203608c1b6044820152606401610cb0565b6000612bfe8284615485565b9050600e548110612c6a5760405162461bcd60e51b815260206004820152603060248201527f5661756c74206973206e6f742062656c6f77206d696e696d756d20636f6c6c6160448201526f746572616c2070657263656e7461676560801b6064820152608401610cb0565b601c54612c7882600a615466565b11612cc55760405162461bcd60e51b815260206004820152601d60248201527f5661756c74206973206e6f742061626f7665206761696e20726174696f0000006044820152606401610cb0565b602054612cd390600a61560c565b612cdd9083615485565b91506000601b5483612cef9190615485565b90506012548111612cfd5750815b601e546040516370a0823160e01b815233600482015282916001600160a01b0316906370a0823190602401602060405180830381865afa158015612d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d699190615720565b1015612dd15760405162461bcd60e51b815260206004820152603160248201527f546f6b656e2062616c616e636520746f6f206c6f7720746f20706179206f6666604482015270081bdd5d1cdd185b991a5b99c81919589d607a1b6064820152608401610cb0565b80602154612ddf91906154a7565b6021556000612ded8a611b7d565b9050612df982876154a7565b60008b8152601660209081526040808320939093556010548c83526018909152918120549091612e2a918590611ace565b60008c815260156020526040902054909150612e479082906154a7565b60008c815260156020526040808220929092558b81522054612e6a908290615510565b60008b815260156020526040808220929092558c81522054612e8d9083906154a7565b60008c815260156020908152604080832093909355338252602290522054612eb6908390615510565b33600081815260226020526040902091909155601e54612ee3916001600160a01b03909116903086614437565b7f4d151d3a98b83151d51917640c221f8c8e3c054422ea1b48dcbbd57e3f4210d58b612f0e8d611ec7565b604080519283526001600160a01b0390911660208301523390820152606081018590526080810184905260a0810183905260c00160405180910390a15050505050505050505050565b606060028054610e64906154db565b80612f708161441a565b612f8c5760405162461bcd60e51b8152600401610cb090615665565b60008181526018602052604090205461271010801590612fb9575060008181526018602052604090205415155b612fd55760405162461bcd60e51b8152600401610cb09061569c565b83612fdf8161441a565b612ffb5760405162461bcd60e51b8152600401610cb0906156c9565b3361300582611ec7565b6001600160a01b03161461302b5760405162461bcd60e51b8152600401610cb090615790565b61303361400b565b600084116130835760405162461bcd60e51b815260206004820152601b60248201527f4d75737420626f72726f77206e6f6e2d7a65726f20616d6f756e7400000000006044820152606401610cb0565b61308b612a01565b8411156130f25760405162461bcd60e51b815260206004820152602f60248201527f626f72726f77546f6b656e3a2043616e6e6f74206d696e74206f76657220617660448201526e30b4b630b136329039bab838363c9760891b6064820152608401610cb0565b6000846130fe8761299a565b6131089190615510565b90506013548111156131675760405162461bcd60e51b815260206004820152602260248201527f626f72726f77546f6b656e3a206d6178206c6f616e2063617020726561636865604482015261321760f11b6064820152608401610cb0565b61317086613acd565b811161317b57600080fd5b600086815260156020526040902054613194908261200e565b6132065760405162461bcd60e51b815260206004820152603a60248201527f426f72726f7720776f756c6420707574207661756c742062656c6f77206d696e60448201527f696d756d20636f6c6c61746572616c2070657263656e746167650000000000006064820152608401610cb0565b6012548561321388613acd565b61321d9190615510565b101561323b5760405162461bcd60e51b8152600401610cb090615739565b6000868152601660209081526040808320849055601154878452601890925282205461326991908490611ace565b6000888152601560205260409020549091506132869082906154a7565b6000888152601560205260408082209290925586815220546132a9908290615510565b600086815260156020526040902055601e546132cf906001600160a01b0316338861461d565b856021546132dd9190615510565b60215560408051888152602081018890527f3e08df88d8e28f37df9bf227d3142ac506a364403445661a60891a49ed6792ca910160405180910390a150506133256001600055565b5050505050565b600d54604080516350d25bcd60e01b815290516000926001600160a01b0316916350d25bcd9160048083019260209291908290030181865afa158015612a4a573d6000803e3d6000fd5b61337e61408a565b6001600160a01b0381166133e05760405162461bcd60e51b8152602060048201526024808201527f53746162696c697479506f6f6c2063616e6e6f74206265207a65726f206164646044820152637265737360e01b6064820152608401610cb0565b602480546001600160a01b0319166001600160a01b0383169081179091556040519081527f0644c4f539d7f787d2287c12d9425e80aefc8bdae99c70af4ca66fb0742577e890602001610f9d565b6125713383836147e7565b61344161408a565b8051613454906029906020840190614f49565b507f0d82453dd4ad18b5ce3db08c34a39340ad2bf15046a7d0e86aa075483eb121d881604051610f9d91906150e1565b601d546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156134cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f19190615720565b601f546134fc61332c565b6135069190615466565b612a6e9190615466565b60008161351c8161441a565b6135385760405162461bcd60e51b8152600401610cb0906156c9565b600061354384613acd565b600085815260156020526040902054909150158061355f575080155b1561356e576000925050612994565b600084815260156020526040812054819061358990846141a2565b9092509050600061359a8284615485565b601c549091506135ab82600a615466565b116135bd576001955050505050612994565b6000955050505050612994565b6000816135d68161441a565b6135f25760405162461bcd60e51b8152600401610cb0906156c9565b60006135fd84613acd565b6000858152601560205260409020549091501580613619575080155b15613628576000925050612994565b600084815260156020526040812054819061364390846141a2565b909250905060006136548284615485565b9050600e548110156135bd576001955050505050612994565b613677338361422b565b6136935760405162461bcd60e51b8152600401610cb090615618565b61369f848484846148b6565b50505050565b6136ad61408a565b602780546001600160a01b0319166001600160a01b0383169081179091556040519081527f66fc0187dfabf79860e1b18e6c175c92baf9ed88c8a01d0bfdb97d1f0450f7f790602001610f9d565b6060613706826140e4565b60006137106148e9565b600b5490915060ff1615610e4f57600081511161373c5760405180602001604052806000815250613767565b80613746846148f8565b6040516020016137579291906157c7565b6040516020818303038152906040525b9392505050565b816137788161441a565b6137945760405162461bcd60e51b8152600401610cb090615665565b600081815260186020526040902054612710108015906137c1575060008181526018602052604090205415155b6137dd5760405162461bcd60e51b8152600401610cb09061569c565b826137e78161441a565b6138035760405162461bcd60e51b8152600401610cb0906156c9565b3361380d82611ec7565b6001600160a01b0316146138335760405162461bcd60e51b8152600401610cb090615790565b60008311801561384557506127108311155b6138915760405162461bcd60e51b815260206004820152601b60248201527f75706461746546726f6e74456e643a2063616e6e6f74206265203000000000006044820152606401610cb0565b60008481526018602090815260409182902085905581518681529081018590527fbfdd5aecf44aa804bf11f070a41765d280dab82adbfd1c55e1e85b7d5b7920b491015b60405180910390a150505050565b6138eb61400b565b336000908152602260205260409020546139475760405162461bcd60e51b815260206004820152601c60248201527f446f6e2774206861766520616e797468696e6720666f7220796f752e000000006044820152606401610cb0565b3360008181526022602052604081208054919055601d549091613974916001600160a01b0316908361461d565b50610e426001600055565b806139898161441a565b6139a55760405162461bcd60e51b8152600401610cb090615665565b600081815260186020526040902054612710108015906139d2575060008181526018602052604090205415155b6139ee5760405162461bcd60e51b8152600401610cb09061569c565b836139f88161441a565b613a145760405162461bcd60e51b8152600401610cb0906156c9565b6027546001600160a01b03161580613a3657506027546001600160a01b031633145b613a525760405162461bcd60e51b8152600401610cb0906156f7565b42841015613aad5760405162461bcd60e51b815260206004820152602260248201527f7061796261636b546f6b656e416c6c3a20646561646c696e6520657870697265604482015261321760f11b6064820152608401610cb0565b6000613ab88661299a565b9050613ac5868286611308565b505050505050565b60008061123983614742565b600081613ae58161441a565b613b015760405162461bcd60e51b8152600401610cb0906156c9565b6000613b0c84613acd565b6000858152601560205260409020549091501580613b28575080155b15613b37576000925050612994565b6000848152601560205260408120548190613b5290846141a2565b9092509050613b618183615485565b9695505050505050565b613b7361408a565b613b7f600c8383614fcd565b507ffda45751019c07e08a3ebf7d73a4aea1a6c36bee12d87089096012911a756ab5600c60405161118391906157f6565b613bb861408a565b80613bfe5760405162461bcd60e51b815260206004820152601660248201527504465627420526174696f2063616e6e6f7420626520360541b6044820152606401610cb0565b601b8190556040518181527f199e93b2fae27b389e2d09761871573f60121b8521be96b8f28c83bf94846ac290602001610f9d565b81613c3d8161441a565b613c595760405162461bcd60e51b8152600401610cb0906156c9565b6027546001600160a01b03161580613c7b57506027546001600160a01b031633145b613c975760405162461bcd60e51b8152600401610cb0906156f7565b600083815260156020526040812054613cb1908490615510565b600085815260156020526040902054909150811015613ccf57600080fd5b6000848152601560205260409020819055601d54613cf8906001600160a01b0316333086614437565b60408051858152602081018590527f52c4e7127ec34e8fc95f09ce2d06b4f00acca12ccbcdfb246ef67ee6aefe068d91016138d5565b613d3661408a565b6001600160a01b038116613d9b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610cb0565b611fce8161464d565b613dac61408a565b6103e8811015613e155760405162461bcd60e51b815260206004820152602e60248201527f6761696e526174696f2063616e6e6f74206265206c657373207468616e206f7260448201526d020657175616c20746f20313030360941b6064820152608401610cb0565b601c8190556040518181527fb6d384ad48d9c5c042c81fa0f88d8061ef87b38475101d6aa5f9ae5a8274a64e90602001610f9d565b613e5684848484613f83565b6001811115613ec55760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b6064820152608401610cb0565b816001600160a01b038516613f2157613f1c81600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b613f44565b836001600160a01b0316856001600160a01b031614613f4457613f448582614995565b6001600160a01b038416613f6057613f5b81614a32565b613325565b846001600160a01b0316846001600160a01b031614613325576133258482614ae1565b600181111561369f576001600160a01b03841615613fc9576001600160a01b03841660009081526004602052604081208054839290613fc39084906154a7565b90915550505b6001600160a01b0383161561369f576001600160a01b03831660009081526004602052604081208054839290614000908490615510565b909155505050505050565b6002600054141561405e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cb0565b6002600055565b60006001600160e01b0319821663780e9d6360e01b1480610e4f5750610e4f82614b25565b6028546001600160a01b03163314610e425760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610cb0565b6140ed8161441a565b611fce5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610cb0565b600081815260056020526040902080546001600160a01b0319166001600160a01b038416908117909155819061416982611ec7565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000806141ad61332c565b6141b657600080fd5b6000601f546141c361332c565b6141cd9087615466565b6141d79190615466565b9050848110156141e657600080fd5b60006141f66305f5e10086615466565b90508481101561420557600080fd5b6000614212836064615466565b905082811161422057600080fd5b969095509350505050565b60008061423783611ec7565b9050806001600160a01b0316846001600160a01b0316148061427e57506001600160a01b0380821660009081526006602090815260408083209388168352929052205460ff165b806112395750836001600160a01b031661429784610fa8565b6001600160a01b031614949350505050565b826001600160a01b03166142bc82611ec7565b6001600160a01b0316146142e25760405162461bcd60e51b8152600401610cb09061589e565b6001600160a01b0382166143445760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610cb0565b6143518383836001614b75565b826001600160a01b031661436482611ec7565b6001600160a01b03161461438a5760405162461bcd60e51b8152600401610cb09061589e565b600081815260056020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260048552838620805460001901905590871680865283862080546001019055868652600390945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000908152600360205260409020546001600160a01b0316151590565b6040516001600160a01b038085166024830152831660448201526064810182905261369f9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614b81565b6001600160a01b0382166144f85760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610cb0565b6145018161441a565b1561454e5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610cb0565b61455c600083836001614b75565b6145658161441a565b156145b25760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610cb0565b6001600160a01b038216600081815260046020908152604080832080546001019055848352600390915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6040516001600160a01b0383166024820152604481018290526110e090849063a9059cbb60e01b9060640161446b565b602880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006146aa82611ec7565b90506146ba816000846001614b75565b6146c382611ec7565b600083815260056020908152604080832080546001600160a01b03199081169091556001600160a01b0385168085526004845282852080546000190190558785526003909352818420805490911690555192935084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60008181526016602090815260408083205460179092528220548291429183901580159061477257506000601454115b156147dd5760008681526017602052604081205461479090856154a7565b905060006127106301e1855883866014546147ab9190615466565b6147b59190615466565b6147bf9190615485565b6147c99190615485565b92508290506147d88482615510565b935050505b9590945092505050565b816001600160a01b0316836001600160a01b031614156148495760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610cb0565b6001600160a01b03838116600081815260066020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6148c18484846142a9565b6148cd84848484614c53565b61369f5760405162461bcd60e51b8152600401610cb0906158e3565b6060600c8054610e64906154db565b6060600061490583614d51565b600101905060008167ffffffffffffffff8111156149255761492561525a565b6040519080825280601f01601f19166020018201604052801561494f576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846149885761498d565b614959565b509392505050565b600060016149a284612195565b6149ac91906154a7565b6000838152600860205260409020549091508082146149ff576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b600954600090614a44906001906154a7565b6000838152600a602052604081205460098054939450909284908110614a6c57614a6c61577a565b906000526020600020015490508060098381548110614a8d57614a8d61577a565b6000918252602080832090910192909255828152600a90915260408082208490558582528120556009805480614ac557614ac5615935565b6001900381819060005260206000200160009055905550505050565b6000614aec83612195565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b60006001600160e01b031982166380ac58cd60e01b1480614b5657506001600160e01b03198216635b5e139f60e01b145b80610e4f57506301ffc9a760e01b6001600160e01b0319831614610e4f565b61369f84848484613e4a565b6000614bd6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614e299092919063ffffffff16565b8051909150156110e05780806020019051810190614bf491906154be565b6110e05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610cb0565b60006001600160a01b0384163b15614d4657604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290614c9790339089908890889060040161594b565b6020604051808303816000875af1925050508015614cd2575060408051601f3d908101601f19168201909252614ccf9181019061597e565b60015b614d2c573d808015614d00576040519150601f19603f3d011682016040523d82523d6000602084013e614d05565b606091505b508051614d245760405162461bcd60e51b8152600401610cb0906158e3565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611239565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310614d905772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310614dbc576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310614dda57662386f26fc10000830492506010015b6305f5e1008310614df2576305f5e100830492506008015b6127108310614e0657612710830492506004015b60648310614e18576064830492506002015b600a8310610e4f5760010192915050565b6060611239848460008585600080866001600160a01b03168587604051614e50919061599b565b60006040518083038185875af1925050503d8060008114614e8d576040519150601f19603f3d011682016040523d82523d6000602084013e614e92565b606091505b5091509150614ea387838387614eae565b979650505050505050565b60608315614f1a578251614f13576001600160a01b0385163b614f135760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610cb0565b5081611239565b6112398383815115614f2f5781518083602001fd5b8060405162461bcd60e51b8152600401610cb091906150e1565b828054614f55906154db565b90600052602060002090601f016020900481019282614f775760008555614fbd565b82601f10614f9057805160ff1916838001178555614fbd565b82800160010185558215614fbd579182015b82811115614fbd578251825591602001919060010190614fa2565b50614fc9929150615041565b5090565b828054614fd9906154db565b90600052602060002090601f016020900481019282614ffb5760008555614fbd565b82601f106150145782800160ff19823516178555614fbd565b82800160010185558215614fbd579182015b82811115614fbd578235825591602001919060010190615026565b5b80821115614fc95760008155600101615042565b6001600160e01b031981168114611fce57600080fd5b60006020828403121561507e57600080fd5b813561376781615056565b60005b838110156150a457818101518382015260200161508c565b8381111561369f5750506000910152565b600081518084526150cd816020860160208601615089565b601f01601f19169290920160200192915050565b60208152600061376760208301846150b5565b80356001600160a01b038116811461510b57600080fd5b919050565b60006020828403121561512257600080fd5b613767826150f4565b60006020828403121561513d57600080fd5b5035919050565b6000806040838503121561515757600080fd5b615160836150f4565b946020939093013593505050565b6000806040838503121561518157600080fd5b50508035926020909101359150565b6000806000606084860312156151a557600080fd5b6151ae846150f4565b92506151bc602085016150f4565b9150604084013590509250925092565b6000806000606084860312156151e157600080fd5b505081359360208301359350604090920135919050565b8015158114611fce57600080fd5b60006020828403121561521857600080fd5b8135613767816151f8565b6000806040838503121561523657600080fd5b61523f836150f4565b9150602083013561524f816151f8565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff8084111561528b5761528b61525a565b604051601f8501601f19908116603f011681019082821181831017156152b3576152b361525a565b816040528093508581528686860111156152cc57600080fd5b858560208301376000602087830101525050509392505050565b6000602082840312156152f857600080fd5b813567ffffffffffffffff81111561530f57600080fd5b8201601f8101841361532057600080fd5b61123984823560208401615270565b6000806000806080858703121561534557600080fd5b61534e856150f4565b935061535c602086016150f4565b925060408501359150606085013567ffffffffffffffff81111561537f57600080fd5b8501601f8101871361539057600080fd5b61539f87823560208401615270565b91505092959194509250565b600080602083850312156153be57600080fd5b823567ffffffffffffffff808211156153d657600080fd5b818501915085601f8301126153ea57600080fd5b8135818111156153f957600080fd5b86602082850101111561540b57600080fd5b60209290920196919550909350505050565b6000806040838503121561543057600080fd5b615439836150f4565b9150615447602084016150f4565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561548057615480615450565b500290565b6000826154a257634e487b7160e01b600052601260045260246000fd5b500490565b6000828210156154b9576154b9615450565b500390565b6000602082840312156154d057600080fd5b8151613767816151f8565b600181811c908216806154ef57607f821691505b6020821081141561299457634e487b7160e01b600052602260045260246000fd5b6000821982111561552357615523615450565b500190565b600181815b8085111561556357816000190482111561554957615549615450565b8085161561555657918102915b93841c939080029061552d565b509250929050565b60008261557a57506001610e4f565b8161558757506000610e4f565b816001811461559d57600281146155a7576155c3565b6001915050610e4f565b60ff8411156155b8576155b8615450565b50506001821b610e4f565b5060208310610133831016604e8410600b84101617156155e6575081810a610e4f565b6155f08383615528565b806000190482111561560457615604615450565b029392505050565b6000613767838361556b565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6020808252601e908201527f66726f6e7420656e64207661756c7420646f6573206e6f742065786973740000604082015260600190565b602080825260139082015272119c9bdb9d08195b99081b9bdd081859191959606a1b604082015260600190565b60208082526014908201527315985d5b1d08191bd95cc81b9bdd08195e1a5cdd60621b604082015260600190565b6020808252600f908201526e36bab9ba103ab9b2903937baba32b960891b604082015260600190565b60006020828403121561573257600080fd5b5051919050565b60208082526021908201527f5661756c7420646562742063616e277420626520756e646572206d696e4465626040820152601d60fa1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60208082526019908201527f5661756c74206973206e6f74206f776e656420627920796f7500000000000000604082015260600190565b600083516157d9818460208801615089565b8351908301906157ed818360208801615089565b01949350505050565b600060208083526000845481600182811c91508083168061581857607f831692505b85831081141561583657634e487b7160e01b85526022600452602485fd5b87860183815260200181801561585357600181146158645761588f565b60ff1986168252878201965061588f565b60008b81526020902060005b8681101561588957815484820152908501908901615870565b83019750505b50949998505050505050505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613b61908301846150b5565b60006020828403121561599057600080fd5b815161376781615056565b600082516159ad818460208701615089565b919091019291505056fea264697066735822122029cb81d5165be54f4036811dd4e81e0d784d1562404c96ca7d292941953b652b64736f6c634300080b0033000000000000000000000000b057c5d7a95a581d6b9c192352f679541bde69bf000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000a3fa99a148fa48d14ed51d610c367c61876997f1000000000000000000000000cc03032fbf096f14a2de8809c79d8b584151212b00000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000010777374455448204d4149205661756c74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007575354454d5654000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d58577663746762545943486469677a6a7951626765474e4e3935486d5173315255774c5147505934764e63770000000000000000000000

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

000000000000000000000000b057c5d7a95a581d6b9c192352f679541bde69bf000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000a3fa99a148fa48d14ed51d610c367c61876997f1000000000000000000000000cc03032fbf096f14a2de8809c79d8b584151212b00000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000010777374455448204d4149205661756c74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007575354454d5654000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d58577663746762545943486469677a6a7951626765474e4e3935486d5173315255774c5147505934764e63770000000000000000000000

-----Decoded View---------------
Arg [0] : ethPriceSourceAddress (address): 0xb057c5d7a95a581d6b9c192352f679541bde69bf
Arg [1] : minimumCollateralPercentage (uint256): 130
Arg [2] : name (string): wstETH MAI Vault
Arg [3] : symbol (string): WSTEMVT
Arg [4] : _mai (address): 0xa3fa99a148fa48d14ed51d610c367c61876997f1
Arg [5] : _collateral (address): 0xcc03032fbf096f14a2de8809c79d8b584151212b
Arg [6] : baseURI (string): ipfs://QmXWvctgbTYCHdigzjyQbgeGNN95HmQs1RUwLQGPY4vNcw

-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 000000000000000000000000b057c5d7a95a581d6b9c192352f679541bde69bf
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000082
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [4] : 000000000000000000000000a3fa99a148fa48d14ed51d610c367c61876997f1
Arg [5] : 000000000000000000000000cc03032fbf096f14a2de8809c79d8b584151212b
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000010
Arg [8] : 777374455448204d4149205661756c7400000000000000000000000000000000
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [10] : 575354454d565400000000000000000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000035
Arg [12] : 697066733a2f2f516d58577663746762545943486469677a6a7951626765474e
Arg [13] : 4e3935486d5173315255774c5147505934764e63770000000000000000000000


Deployed ByteCode Sourcemap

119221:11026:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;128605:332;;;:::i;:::-;;60291:171;;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;60291:171:0;;;;;;;;89654:28;;;;;-1:-1:-1;;;;;89654:28:0;;;;;;-1:-1:-1;;;;;756:32:1;;;738:51;;726:2;711:18;89654:28:0;592:203:1;89689:18:0;;;;;-1:-1:-1;;;;;89689:18:0;;;36885:100;;;:::i;:::-;;;;;;;:::i;122732:331::-;;;;;;:::i;:::-;;:::i;38397:171::-;;;;;;:::i;:::-;;:::i;37915:416::-;;;;;;:::i;:::-;;:::i;123874:244::-;;;;;;:::i;:::-;;:::i;106499:799::-;;;;;;:::i;:::-;;:::i;:::-;;;2918:25:1;;;2906:2;2891:18;106499:799:0;2772:177:1;54551:113:0;54639:10;:17;54551:113;;88771:25;;;;;;89714:18;;;;;-1:-1:-1;;;;;89714:18:0;;;39097:335;;;;;;:::i;:::-;;:::i;88950:17::-;;;;;;89033:55;;;;;;:::i;:::-;;;;;;;;;;;;;;54219:256;;;;;;:::i;:::-;;:::i;89354:24::-;;;;;;104328:1151;;;;;;:::i;:::-;;:::i;130116:128::-;;;;;;:::i;:::-;;:::i;124296:258::-;;;;;;:::i;:::-;;:::i;126713:277::-;;;;;;:::i;:::-;;:::i;127204:303::-;;;;;;:::i;:::-;;:::i;39503:185::-;;;;;;:::i;:::-;;:::i;129433:251::-;;;;;;:::i;:::-;;:::i;88638:34::-;;;;;-1:-1:-1;;;;;88638:34:0;;;89535:28;;;;;;92983:104;;;;;;:::i;:::-;;:::i;54741:233::-;;;;;;:::i;:::-;;:::i;98385:533::-;;;;;;:::i;:::-;;:::i;89767:24::-;;;;;-1:-1:-1;;;89767:24:0;;;;;;;;;4378:4:1;4366:17;;;4348:36;;4336:2;4321:18;89767:24:0;4206:184:1;107532:896:0;;;;;;:::i;:::-;;:::i;89417:16::-;;;;;-1:-1:-1;;;;;89417:16:0;;;99034:259;;;:::i;129061:123::-;;;;;;:::i;:::-;;:::i;128219:325::-;;;;;;:::i;:::-;;:::i;124705:219::-;;;;;;:::i;:::-;;:::i;36595:223::-;;;;;;:::i;:::-;;:::i;106033:249::-;;;;;;:::i;:::-;;:::i;125091:219::-;;;;;;:::i;:::-;;:::i;97558:429::-;;;;;;:::i;:::-;;:::i;125511:183::-;;;;;;:::i;:::-;;:::i;125900:::-;;;;;;:::i;:::-;;:::i;36326:207::-;;;;;;:::i;:::-;;:::i;118209:103::-;;;:::i;88803:25::-;;;;;;101075:775;;;;;;:::i;:::-;;:::i;99471:578::-;;;;;;:::i;:::-;;:::i;126260:277::-;;;;;;:::i;:::-;;:::i;117561:87::-;117634:6;;-1:-1:-1;;;;;117634:6:0;117561:87;;114220:2095;;;;;;:::i;:::-;;:::i;95732:454::-;;;;;;:::i;:::-;;:::i;92635:110::-;;;:::i;111411:2349::-;;;;;;:::i;:::-;;:::i;37054:104::-;;;:::i;102211:1365::-;;;;;;:::i;:::-;;:::i;89097:47::-;;;;;;:::i;:::-;;;;;;;;;;;;;;94150:114;;;:::i;123300:231::-;;;;;;:::i;:::-;;:::i;89203:23::-;;;;;;38640:155;;;;;;:::i;:::-;;:::i;89442:43::-;;;;;;93630:93;93705:10;;93630:93;;88733:25;;;;;;121486:149;;;;;;:::i;:::-;;:::i;89572:44::-;;;;;;:::i;:::-;;;;;;;;;;;;;;93237:252;;;:::i;110310:702::-;;;;;;:::i;:::-;;:::i;109358:753::-;;;;;;:::i;:::-;;:::i;39759:322::-;;;;;;:::i;:::-;;:::i;129983:125::-;;;;;;:::i;:::-;;:::i;60013:18::-;;;;;;;;;89494:34;;;;;;60807:370;;;;;;:::i;:::-;;:::i;127776:311::-;;;;;;:::i;:::-;;:::i;93877:95::-;88932:3;93877:95;;88897:38;;88932:3;88897:38;;89323:24;;;;;;105595:266;;;:::i;103584:405::-;;;;;;:::i;:::-;;:::i;88866:22::-;;;;;;95375:151;;;;;;:::i;:::-;;:::i;88976:50::-;;;;;;:::i;:::-;;;;;;;;;;;;;;89151:43;;;;;;:::i;:::-;;;;;;;;;;;;;;89387:23;;;;;-1:-1:-1;;;;;89387:23:0;;;108578:585;;;;;;:::i;:::-;;:::i;129832:143::-;;;;;;:::i;:::-;;:::i;88681:43::-;;;;;;38866:164;;;;;;:::i;:::-;-1:-1:-1;;;;;38987:25:0;;;38963:4;38987:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;38866:164;122257:206;;;;;;:::i;:::-;;:::i;89263:21::-;;;;;;100327:454;;;;;;:::i;:::-;;:::i;88837:22::-;;;;;;89623;;;;;;118467:201;;;;;;:::i;:::-;;:::i;89739:21::-;;;;;-1:-1:-1;;;;;89739:21:0;;;121832:233;;;;;;:::i;:::-;;:::i;128605:332::-;121097:3;;-1:-1:-1;;;;;121097:3:0;121104:10;121097:17;;:38;;-1:-1:-1;121118:3:0;;-1:-1:-1;;;;;121118:3:0;121125:10;121118:17;121097:38;:63;;;-1:-1:-1;121150:10:0;121139:7;117634:6;;-1:-1:-1;;;;;117634:6:0;;117561:87;121139:7;-1:-1:-1;;;;;121139:21:0;;121097:63;121089:107;;;;-1:-1:-1;;;121089:107:0;;7898:2:1;121089:107:0;;;7880:21:1;7937:2;7917:18;;;7910:30;7976:33;7956:18;;;7949:61;8027:18;;121089:107:0;;;;;;;;;87676:21:::1;:19;:21::i;:::-;128682:15:::2;88542:5;128708:8;;128700:7;;:16;;;;:::i;:::-;:31;;;;:::i;:::-;128765:3;::::0;128778::::2;::::0;128784:7:::2;::::0;128682:49;;-1:-1:-1;;;;;;128765:3:0;;::::2;::::0;:12:::2;::::0;128778:3;;::::2;::::0;128784:15:::2;::::0;128682:49;;128784:15:::2;:::i;:::-;128765:37;::::0;-1:-1:-1;;;;;;128765:37:0::2;::::0;;;;;;-1:-1:-1;;;;;9037:32:1;;;128765:37:0::2;::::0;::::2;9019:51:1::0;9086:18;;;9079:34;8992:18;;128765:37:0::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;128840:3:0::2;::::0;128853::::2;::::0;128840:26:::2;::::0;-1:-1:-1;;;128840:26:0;;-1:-1:-1;;;;;128853:3:0;;::::2;128840:26;::::0;::::2;9019:51:1::0;9086:18;;;9079:34;;;128840:3:0;::::2;::::0;:12:::2;::::0;8992:18:1;;128840:26:0::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;128882:25;128899:7;;128882:25;;;;2918::1::0;;2906:2;2891:18;;2772:177;128882:25:0::2;;;;;;;;-1:-1:-1::0;128928:1:0::2;128918:7;:11:::0;87720:20:::1;87114:1:::0;88240:7;:22;88057:213;87720:20:::1;128605:332::o:0;60291:171::-;60394:4;60418:36;60442:11;60418:23;:36::i;:::-;60411:43;60291:171;-1:-1:-1;;60291:171:0:o;36885:100::-;36939:13;36972:5;36965:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36885:100;:::o;122732:331::-;117447:13;:11;:13::i;:::-;-1:-1:-1;;;;;122854:35:0;::::1;122846:86;;;::::0;-1:-1:-1;;;122846:86:0;;9961:2:1;122846:86:0::1;::::0;::::1;9943:21:1::0;10000:2;9980:18;;;9973:30;10039:34;10019:18;;;10012:62;-1:-1:-1;;;10090:18:1;;;10083:35;10135:19;;122846:86:0::1;9759:401:1::0;122846:86:0::1;122943:14;:52:::0;;-1:-1:-1;;;;;;122943:52:0::1;-1:-1:-1::0;;;;;122943:52:0;::::1;::::0;;::::1;::::0;;;123011:44:::1;::::0;738:51:1;;;123011:44:0::1;::::0;726:2:1;711:18;123011:44:0::1;;;;;;;;122732:331:::0;:::o;38397:171::-;38473:7;38493:23;38508:7;38493:14;:23::i;:::-;-1:-1:-1;38536:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;38536:24:0;;38397:171::o;37915:416::-;37996:13;38012:23;38027:7;38012:14;:23::i;:::-;37996:39;;38060:5;-1:-1:-1;;;;;38054:11:0;:2;-1:-1:-1;;;;;38054:11:0;;;38046:57;;;;-1:-1:-1;;;38046:57:0;;10367:2:1;38046:57:0;;;10349:21:1;10406:2;10386:18;;;10379:30;10445:34;10425:18;;;10418:62;-1:-1:-1;;;10496:18:1;;;10489:31;10537:19;;38046:57:0;10165:397:1;38046:57:0;11322:10;-1:-1:-1;;;;;38138:21:0;;;;:62;;-1:-1:-1;38163:37:0;38180:5;11322:10;38866:164;:::i;38163:37::-;38116:173;;;;-1:-1:-1;;;38116:173:0;;10769:2:1;38116:173:0;;;10751:21:1;10808:2;10788:18;;;10781:30;10847:34;10827:18;;;10820:62;10918:31;10898:18;;;10891:59;10967:19;;38116:173:0;10567:425:1;38116:173:0;38302:21;38311:2;38315:7;38302:8;:21::i;:::-;37985:346;37915:416;;:::o;123874:244::-;117447:13;:11;:13::i;:::-;88542:5:::1;123960:11;123967:4:::0;123960:6;:11:::1;:::i;:::-;123959:27;123951:66;;;::::0;-1:-1:-1;;;123951:66:0;;11332:2:1;123951:66:0::1;::::0;::::1;11314:21:1::0;11371:2;11351:18;;;11344:30;11410:28;11390:18;;;11383:56;11456:18;;123951:66:0::1;11130:350:1::0;123951:66:0::1;124028:8;:15:::0;;;124054:6:::1;:11:::0;;;124081:29:::1;::::0;;11659:25:1;;;11715:2;11700:18;;11693:34;;;124081:29:0::1;::::0;11632:18:1;124081:29:0::1;;;;;;;;123874:244:::0;;:::o;106499:799::-;106556:7;106576:20;106599:18;106609:7;106599:9;:18::i;:::-;106648:24;;;;:15;:24;;;;;;106576:41;;-1:-1:-1;106648:29:0;;:63;;-1:-1:-1;106694:17:0;;106648:63;:106;;;;106729:25;106746:7;106729:16;:25::i;:::-;106728:26;106648:106;106630:171;;;-1:-1:-1;106788:1:0;;106499:799;-1:-1:-1;;106499:799:0:o;106630:171::-;106829:17;106908:24;;;:15;:24;;;;;;106860:118;;106951:12;106860:29;:118::i;:::-;106813:165;-1:-1:-1;;106995:14:0;106991:55;;-1:-1:-1;107033:1:0;;106499:799;-1:-1:-1;;;106499:799:0:o;106991:55::-;107087:19;;107083:23;;:2;:23;:::i;:::-;107070:37;;:9;:37;:::i;:::-;107058:49;;107120:16;107151:9;;107139;:21;;;;:::i;:::-;107120:40;;107205:7;;107193:8;:19;107189:72;;-1:-1:-1;107240:9:0;107189:72;107281:8;106499:799;-1:-1:-1;;;;106499:799:0:o;39097:335::-;39292:41;11322:10;39325:7;39292:18;:41::i;:::-;39284:99;;;;-1:-1:-1;;;39284:99:0;;;;;;;:::i;:::-;39396:28;39406:4;39412:2;39416:7;39396:9;:28::i;54219:256::-;54316:7;54352:23;54369:5;54352:16;:23::i;:::-;54344:5;:31;54336:87;;;;-1:-1:-1;;;54336:87:0;;13728:2:1;54336:87:0;;;13710:21:1;13767:2;13747:18;;;13740:30;13806:34;13786:18;;;13779:62;-1:-1:-1;;;13857:18:1;;;13850:41;13908:19;;54336:87:0;13526:407:1;54336:87:0;-1:-1:-1;;;;;;54441:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;54219:256::o;104328:1151::-;104452:6;92247:16;92255:7;92247;:16::i;:::-;92239:59;;;;-1:-1:-1;;;92239:59:0;;;;;;;:::i;:::-;92317:17;;;;:8;:17;;;;;;88542:5;-1:-1:-1;92317:33:0;;;:58;;-1:-1:-1;92374:1:0;92354:17;;;:8;:17;;;;;;:21;;92317:58;92309:90;;;;-1:-1:-1;;;92309:90:0;;;;;;;:::i;:::-;104472:7:::1;92121:16;92129:7;92121;:16::i;:::-;92113:49;;;;-1:-1:-1::0;;;92113:49:0::1;;;;;;;:::i;:::-;91949:6:::2;::::0;-1:-1:-1;;;;;91949:6:0::2;:20:::0;;:44:::2;;-1:-1:-1::0;91987:6:0::2;::::0;-1:-1:-1;;;;;91987:6:0::2;91973:10;:20;91949:44;91927:109;;;;-1:-1:-1::0;;;91927:109:0::2;;;;;;;:::i;:::-;104511:3:::3;::::0;:25:::3;::::0;-1:-1:-1;;;104511:25:0;;104525:10:::3;104511:25;::::0;::::3;738:51:1::0;104540:6:0;;-1:-1:-1;;;;;104511:3:0::3;::::0;:13:::3;::::0;711:18:1;;104511:25:0::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:35;;104503:69;;;::::0;-1:-1:-1;;;104503:69:0;;15729:2:1;104503:69:0::3;::::0;::::3;15711:21:1::0;15768:2;15748:18;;;15741:30;-1:-1:-1;;;15787:18:1;;;15780:51;15848:18;;104503:69:0::3;15527:345:1::0;104503:69:0::3;104585:20;104608:24;104624:7;104608:15;:24::i;:::-;104585:47;;104683:6;104667:12;:22;;104645:111;;;::::0;-1:-1:-1;;;104645:111:0;;16079:2:1;104645:111:0::3;::::0;::::3;16061:21:1::0;16118:2;16098:18;;;16091:30;16157:34;16137:18;;;16130:62;-1:-1:-1;;;16208:18:1;;;16201:37;16255:19;;104645:111:0::3;15877:403:1::0;104645:111:0::3;104820:7;::::0;104792:23:::3;104809:6:::0;104793:12;104792:23:::3;:::i;:::-;104791:36;;:64;;;;104842:12;104831:6;:24;104791:64;104769:147;;;;-1:-1:-1::0;;;104769:147:0::3;;;;;;;:::i;:::-;104978:10;::::0;104929:19:::3;105024:16:::0;;;:8:::3;:16;::::0;;;;;104929:19;;104951:100:::3;::::0;105003:6;;104951:12:::3;:100::i;:::-;104929:122:::0;-1:-1:-1;105096:21:0::3;105111:6:::0;105096:12;:21:::3;:::i;:::-;105064:29;::::0;;;:20:::3;:29;::::0;;;;;;;:53;;;;105157:15:::3;:24:::0;;;;:38:::3;::::0;105184:11;;105157:38:::3;:::i;:::-;105130:24;::::0;;;:15:::3;:24;::::0;;;;;:65;;;;105232:23;;;;;:37:::3;::::0;105258:11;;105232:37:::3;:::i;:::-;105206:23;::::0;;;:15:::3;:23;::::0;;;;:63;105298:13:::3;::::0;:22:::3;::::0;105314:6;;105298:22:::3;:::i;:::-;105282:13;:38:::0;105348:3:::3;::::0;:55:::3;::::0;-1:-1:-1;;;;;105348:3:0::3;105369:10;105389:4;105396:6:::0;105348:20:::3;:55::i;:::-;105429:42;::::0;;16889:25:1;;;16945:2;16930:18;;16923:34;;;16973:18;;;16966:34;;;105429:42:0::3;::::0;16877:2:1;16862:18;105429:42:0::3;;;;;;;104492:987;;92410:1:::1;104328:1151:::0;;;;:::o;130116:128::-;117447:13;:11;:13::i;:::-;130182:6:::1;:14:::0;;-1:-1:-1;;130182:14:0::1;::::0;::::1;;::::0;;::::1;::::0;;;130212:24:::1;::::0;130182:14:::1;130229:6:::0;;;565:14:1;558:22;540:41;;130212:24:0::1;::::0;528:2:1;513:18;130212:24:0::1;400:187:1::0;124296:258:0;117447:13;:11;:13::i;:::-;124417:28:::1;:58:::0;;;124491:55:::1;::::0;2918:25:1;;;124491:55:0::1;::::0;2906:2:1;2891:18;124491:55:0::1;2772:177:1::0;126713:277:0;117447:13;:11;:13::i;:::-;119379:3:::1;126815:11;:22;;126787:92;;;::::0;-1:-1:-1;;;126787:92:0;;17213:2:1;126787:92:0::1;::::0;::::1;17195:21:1::0;17252:2;17232:18;;;17225:30;17291:34;17271:18;;;17264:62;-1:-1:-1;;;17342:18:1;;;17335:35;17387:19;;126787:92:0::1;17011:401:1::0;126787:92:0::1;126890:10;:24:::0;;;126953:29:::1;::::0;2918:25:1;;;126953:29:0::1;::::0;2906:2:1;2891:18;126953:29:0::1;2772:177:1::0;127204:303:0;117447:13;:11;:13::i;:::-;127280:18:::1;127288:9;127280:7;:18::i;:::-;127272:64;;;::::0;-1:-1:-1;;;127272:64:0;;17619:2:1;127272:64:0::1;::::0;::::1;17601:21:1::0;17658:2;17638:18;;;17631:30;17697:34;17677:18;;;17670:62;-1:-1:-1;;;17748:18:1;;;17741:31;17789:19;;127272:64:0::1;17417:397:1::0;127272:64:0::1;127359:19;::::0;;;:8:::1;:19;::::0;;;;;:24;127351:63:::1;;;::::0;-1:-1:-1;;;127351:63:0;;18021:2:1;127351:63:0::1;::::0;::::1;18003:21:1::0;18060:2;18040:18;;;18033:30;18099:28;18079:18;;;18072:56;18145:18;;127351:63:0::1;17819:350:1::0;127351:63:0::1;127425:19;::::0;;;:8:::1;:19;::::0;;;;;;88542:5:::1;127425:34:::0;;127475:24;::::1;::::0;::::1;::::0;127434:9;2918:25:1;;2906:2;2891:18;;2772:177;39503:185:0;39641:39;39658:4;39664:2;39668:7;39641:39;;;;;;;;;;;;:16;:39::i;129433:251::-;121264:3;;-1:-1:-1;;;;;121264:3:0;121271:10;121264:17;121256:57;;;;-1:-1:-1;;;121256:57:0;;18376:2:1;121256:57:0;;;18358:21:1;18415:2;18395:18;;;18388:30;18454:29;18434:18;;;18427:57;18501:18;;121256:57:0;18174:351:1;121256:57:0;129538:3:::1;::::0;:28:::1;::::0;-1:-1:-1;;;129538:28:0;;129560:4:::1;129538:28;::::0;::::1;738:51:1::0;-1:-1:-1;;;;;129538:3:0;;::::1;::::0;:13:::1;::::0;711:18:1;;129538:28:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;129523:11;:43;;129515:80;;;::::0;-1:-1:-1;;;129515:80:0;;18732:2:1;129515:80:0::1;::::0;::::1;18714:21:1::0;18771:2;18751:18;;;18744:30;18810:26;18790:18;;;18783:54;18854:18;;129515:80:0::1;18530:348:1::0;129515:80:0::1;129606:3;::::0;129619::::1;::::0;129606:30:::1;::::0;-1:-1:-1;;;129606:30:0;;-1:-1:-1;;;;;129619:3:0;;::::1;129606:30;::::0;::::1;9019:51:1::0;9086:18;;;9079:34;;;129606:3:0;::::1;::::0;:12:::1;::::0;8992:18:1;;129606:30:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;129652:24:0::1;::::0;2918:25:1;;;129652:24:0::1;::::0;2906:2:1;2891:18;129652:24:0::1;2772:177:1::0;92983:104:0;93039:4;93063:16;93071:7;93063;:16::i;54741:233::-;54816:7;54852:30;54639:10;:17;;54551:113;54852:30;54844:5;:38;54836:95;;;;-1:-1:-1;;;54836:95:0;;19085:2:1;54836:95:0;;;19067:21:1;19124:2;19104:18;;;19097:30;19163:34;19143:18;;;19136:62;-1:-1:-1;;;19214:18:1;;;19207:42;19266:19;;54836:95:0;18883:408:1;54836:95:0;54949:10;54960:5;54949:17;;;;;;;;:::i;:::-;;;;;;;;;54942:24;;54741:233;;;:::o;98385:533::-;98509:7;;98556:10;;98552:306;;88542:5;;98661:19;:17;:19::i;:::-;:34;;;;:::i;:::-;:49;;;;:::i;:::-;98631:8;88932:3;98592:12;98601:3;98592:6;:12;:::i;:::-;:36;;;;:::i;:::-;:47;;;;:::i;:::-;98591:120;;;;:::i;:::-;98583:129;;98552:306;;;88542:5;98811:19;:17;:19::i;:::-;:34;;;;:::i;:::-;88932:3;98753:12;98762:3;98753:6;:12;:::i;:::-;:36;;;;:::i;:::-;98752:94;;;;:::i;:::-;98745:101;;98552:306;98882:28;;98875:35;;:4;:35;:::i;:::-;98868:42;98385:533;-1:-1:-1;;;;;98385:533:0:o;107532:896::-;107592:7;107616:24;;;:15;:24;;;;;;:29;;:59;;;107650:25;107667:7;107650:16;:25::i;:::-;107649:26;107616:59;107612:100;;;-1:-1:-1;107699:1:0;;107532:896;-1:-1:-1;107532:896:0:o;107612:100::-;107722:20;107745:18;107755:7;107745:9;:18::i;:::-;107779:17;107844:24;;;:15;:24;;;;;;107722:41;;-1:-1:-1;107779:17:0;107800:106;;107722:41;107800:29;:106::i;:::-;107776:130;;;107919:16;107950:9;;107938;:21;;;;:::i;:::-;107919:40;-1:-1:-1;107992:13:0;107988:54;;-1:-1:-1;108029:1:0;;107532:896;-1:-1:-1;;;;107532:896:0:o;107988:54::-;108098:7;;108074:19;;108070:23;;:2;:23;:::i;:::-;108056:38;;108057:8;108056:38;:::i;:::-;:49;108052:369;;108251:28;;108228:19;:17;:19::i;:::-;88625:4;108200:9;;108186;:24;;;;:::i;:::-;108185:39;;;;:::i;:::-;:63;;;;:::i;:::-;:94;;;;:::i;108052:369::-;108381:28;;108358:19;:17;:19::i;:::-;88625:4;108332:9;;108320:8;:22;;;;:::i;99034:259::-;99106:10;;99073:7;;99140:14;99106:10;99153:1;99140:14;:::i;:::-;99127:10;:27;;;99173:16;-1:-1:-1;99173:16:0;99165:25;;;;;;99201:21;99207:10;99219:2;99201:5;:21::i;:::-;99238:27;;;19602:25:1;;;99254:10:0;19658:2:1;19643:18;;19636:60;99238:27:0;;19575:18:1;99238:27:0;;;;;;;99283:2;99034:259;-1:-1:-1;99034:259:0:o;129061:123::-;117447:13;:11;:13::i;:::-;129129:2:::1;:8:::0;;;129153:23:::1;::::0;2918:25:1;;;129153:23:0::1;::::0;2906:2:1;2891:18;129153:23:0::1;2772:177:1::0;128219:325:0;128283:9;92247:16;92255:7;92247;:16::i;:::-;92239:59;;;;-1:-1:-1;;;92239:59:0;;;;;;;:::i;:::-;92317:17;;;;:8;:17;;;;;;88542:5;-1:-1:-1;92317:33:0;;;:58;;-1:-1:-1;92374:1:0;92354:17;;;:8;:17;;;;;;:21;;92317:58;92309:90;;;;-1:-1:-1;;;92309:90:0;;;;;;;:::i;:::-;117447:13:::1;:11;:13::i;:::-;128323:18:::2;128331:9;128323:7;:18::i;:::-;128315:67;;;::::0;-1:-1:-1;;;128315:67:0;;19909:2:1;128315:67:0::2;::::0;::::2;19891:21:1::0;19948:2;19928:18;;;19921:30;19987:34;19967:18;;;19960:62;-1:-1:-1;;;20038:18:1;;;20031:34;20082:19;;128315:67:0::2;19707:400:1::0;128315:67:0::2;128423:1;128401:19:::0;;;:8:::2;:19;::::0;;;;;128393:67:::2;;;::::0;-1:-1:-1;;;128393:67:0;;20314:2:1;128393:67:0::2;::::0;::::2;20296:21:1::0;20353:2;20333:18;;;20326:30;20392:33;20372:18;;;20365:61;20443:18;;128393:67:0::2;20112:355:1::0;128393:67:0::2;128493:1;128471:19:::0;;;:8:::2;:19;::::0;;;;;:23;;;;128510:26;::::2;::::0;::::2;::::0;128480:9;2918:25:1;;2906:2;2891:18;;2772:177;124705:219:0;117447:13;:11;:13::i;:::-;124859:7:::1;:18:::0;;;124893:23:::1;::::0;2918:25:1;;;124893:23:0::1;::::0;2906:2:1;2891:18;124893:23:0::1;2772:177:1::0;36595:223:0;36667:7;41482:16;;;:7;:16;;;;;;-1:-1:-1;;;;;41482:16:0;;36731:56;;;;-1:-1:-1;;;36731:56:0;;21030:2:1;36731:56:0;;;21012:21:1;21069:2;21049:18;;;21042:30;-1:-1:-1;;;21088:18:1;;;21081:54;21152:18;;36731:56:0;20828:348:1;106033:249:0;87676:21;:19;:21::i;:::-;-1:-1:-1;;;;;106104:14:0;::::1;;::::0;;;:9:::1;:14;::::0;;;;;106096:60:::1;;;::::0;-1:-1:-1;;;106096:60:0;;21383:2:1;106096:60:0::1;::::0;::::1;21365:21:1::0;21422:2;21402:18;;;21395:30;21461;21441:18;;;21434:58;21509:18;;106096:60:0::1;21181:352:1::0;106096:60:0::1;-1:-1:-1::0;;;;;106184:14:0;;::::1;106167;106184::::0;;;:9:::1;:14;::::0;;;;;;106209:18;;;106238:10:::1;::::0;106184:14;;106238:36:::1;::::0;:10:::1;106194:3:::0;106184:14;106238:23:::1;:36::i;:::-;106085:197;87720:20:::0;87114:1;88240:7;:22;88057:213;87720:20;106033:249;:::o;125091:219::-;117447:13;:11;:13::i;:::-;125245:7:::1;:18:::0;;;125279:23:::1;::::0;2918:25:1;;;125279:23:0::1;::::0;2906:2:1;2891:18;125279:23:0::1;2772:177:1::0;97558:429:0;97668:4;97705:31;97751:17;97782:48;97812:11;97825:4;97782:29;:48::i;:::-;97690:140;;-1:-1:-1;97690:140:0;-1:-1:-1;97843:28:0;97874:35;97690:140;;97874:35;:::i;:::-;97951:28;;-1:-1:-1;97927:52:0;;97558:429;-1:-1:-1;;;;;;97558:429:0:o;125511:183::-;117447:13;:11;:13::i;:::-;-1:-1:-1;;;;;125579:18:0;::::1;125571:63;;;::::0;-1:-1:-1;;;125571:63:0;;22096:2:1;125571:63:0::1;::::0;::::1;22078:21:1::0;;;22115:18;;;22108:30;22174:34;22154:18;;;22147:62;22226:18;;125571:63:0::1;21894:356:1::0;125571:63:0::1;125645:3;:10:::0;;-1:-1:-1;;;;;;125645:10:0::1;-1:-1:-1::0;;;;;125645:10:0;::::1;::::0;;::::1;::::0;;;125671:15:::1;::::0;738:51:1;;;125671:15:0::1;::::0;726:2:1;711:18;125671:15:0::1;592:203:1::0;125900:183:0;117447:13;:11;:13::i;:::-;-1:-1:-1;;;;;125970:18:0;::::1;125962:59;;;::::0;-1:-1:-1;;;125962:59:0;;22457:2:1;125962:59:0::1;::::0;::::1;22439:21:1::0;22496:2;22476:18;;;22469:30;22535;22515:18;;;22508:58;22583:18;;125962:59:0::1;22255:352:1::0;125962:59:0::1;126032:3;:10:::0;;-1:-1:-1;;;;;;126032:10:0::1;-1:-1:-1::0;;;;;126032:10:0;::::1;::::0;;::::1;::::0;;;126058:17:::1;::::0;738:51:1;;;126058:17:0::1;::::0;726:2:1;711:18;126058:17:0::1;592:203:1::0;36326:207:0;36398:7;-1:-1:-1;;;;;36426:19:0;;36418:73;;;;-1:-1:-1;;;36418:73:0;;22814:2:1;36418:73:0;;;22796:21:1;22853:2;22833:18;;;22826:30;22892:34;22872:18;;;22865:62;-1:-1:-1;;;22943:18:1;;;22936:39;22992:19;;36418:73:0;22612:405:1;36418:73:0;-1:-1:-1;;;;;;36509:16:0;;;;;:9;:16;;;;;;;36326:207::o;118209:103::-;117447:13;:11;:13::i;:::-;118274:30:::1;118301:1;118274:18;:30::i;101075:775::-:0;101178:7;91746:16;91754:7;91746;:16::i;:::-;91738:49;;;;-1:-1:-1;;;91738:49:0;;;;;;;:::i;:::-;91826:10;91806:16;91814:7;91806;:16::i;:::-;-1:-1:-1;;;;;91806:30:0;;91798:68;;;;-1:-1:-1;;;91798:68:0;;;;;;;:::i;:::-;87676:21:::1;:19;:21::i;:::-;101247:24:::2;::::0;;;:15:::2;:24;::::0;;;;;:34;-1:-1:-1;101247:34:0::2;101225:121;;;::::0;-1:-1:-1;;;101225:121:0;;23578:2:1;101225:121:0::2;::::0;::::2;23560:21:1::0;23617:2;23597:18;;;23590:30;23656:34;23636:18;;;23629:62;-1:-1:-1;;;23707:18:1;;;23700:35;23752:19;;101225:121:0::2;23376:401:1::0;101225:121:0::2;101359:21;101383:24:::0;;;:15:::2;:24;::::0;;;;;:33:::2;::::0;101410:6;;101383:33:::2;:::i;:::-;101359:57;;101427:12;101442:24;101458:7;101442:15;:24::i;:::-;101427:39:::0;-1:-1:-1;101483:9:0;;101479:204:::2;;101535:38;101553:13;101568:4;101535:17;:38::i;:::-;101509:162;;;::::0;-1:-1:-1;;;101509:162:0;;23984:2:1;101509:162:0::2;::::0;::::2;23966:21:1::0;24023:2;24003:18;;;23996:30;24062:34;24042:18;;;24035:62;24133:32;24113:18;;;24106:60;24183:19;;101509:162:0::2;23782:426:1::0;101509:162:0::2;101695:24;::::0;;;:15:::2;:24;::::0;;;;:40;;;101746:10:::2;::::0;:43:::2;::::0;-1:-1:-1;;;;;101746:10:0::2;101770;101782:6:::0;101746:23:::2;:43::i;:::-;101807:35;::::0;;11659:25:1;;;11715:2;11700:18;;11693:34;;;101807:35:0::2;::::0;11632:18:1;101807:35:0::2;;;;;;;101214:636;;87720:20:::1;87114:1:::0;88240:7;:22;88057:213;99471:578;99552:7;91746:16;91754:7;91746;:16::i;:::-;91738:49;;;;-1:-1:-1;;;91738:49:0;;;;;;;:::i;:::-;91826:10;91806:16;91814:7;91806;:16::i;:::-;-1:-1:-1;;;;;91806:30:0;;91798:68;;;;-1:-1:-1;;;91798:68:0;;;;;;;:::i;:::-;87676:21:::1;:19;:21::i;:::-;99607:18:::2;99617:7;99607:9;:18::i;:::-;:23:::0;99599:62:::2;;;::::0;-1:-1:-1;;;99599:62:0;;24415:2:1;99599:62:0::2;::::0;::::2;24397:21:1::0;24454:2;24434:18;;;24427:30;24493:28;24473:18;;;24466:56;24539:18;;99599:62:0::2;24213:350:1::0;99599:62:0::2;99678:24;::::0;;;:15:::2;:24;::::0;;;;;:29;99674:174:::2;;99769:67;99793:16;99801:7;99793;:16::i;:::-;99811:24;::::0;;;:15:::2;:24;::::0;;;;;99769:10:::2;::::0;-1:-1:-1;;;;;99769:10:0::2;::::0;:67;:23:::2;:67::i;:::-;99860:14;99866:7;99860:5;:14::i;:::-;99894:24;::::0;;;:15:::2;:24;::::0;;;;;;;99887:31;;;99936:20:::2;:29:::0;;;;;99929:36;;;99983:12:::2;:21:::0;;;;;99976:28;;;;100020:21;;2918:25:1;;;100020:21:0::2;::::0;2891:18:1;100020:21:0::2;;;;;;;87720:20:::1;87114:1:::0;88240:7;:22;88057:213;87720:20:::1;99471:578:::0;;:::o;126260:277::-;117447:13;:11;:13::i;:::-;119379:3:::1;126362:11;:22;;126334:92;;;::::0;-1:-1:-1;;;126334:92:0;;24770:2:1;126334:92:0::1;::::0;::::1;24752:21:1::0;24809:2;24789:18;;;24782:30;24848:34;24828:18;;;24821:62;-1:-1:-1;;;24899:18:1;;;24892:35;24944:19;;126334:92:0::1;24568:401:1::0;126334:92:0::1;126437:10;:24:::0;;;126500:29:::1;::::0;2918:25:1;;;126500:29:0::1;::::0;2906:2:1;2891:18;126500:29:0::1;2772:177:1::0;114220:2095:0;114314:7;114284;92121:16;92129:7;92121;:16::i;:::-;92113:49;;;;-1:-1:-1;;;92113:49:0;;;;;;;:::i;:::-;87676:21:::1;:19;:21::i;:::-;114356:13:::2;::::0;-1:-1:-1;;;;;114356:13:0::2;:27:::0;;:58:::2;;-1:-1:-1::0;114401:13:0::2;::::0;-1:-1:-1;;;;;114401:13:0::2;114387:10;:27;114356:58;114334:140;;;::::0;-1:-1:-1;;;114334:140:0;;25176:2:1;114334:140:0::2;::::0;::::2;25158:21:1::0;;;25195:18;;;25188:30;25254:34;25234:18;;;25227:62;25306:18;;114334:140:0::2;24974:356:1::0;114334:140:0::2;114495:20;114518:24;114534:7;114518:15;:24::i;:::-;114495:47:::0;-1:-1:-1;114563:17:0;114555:45:::2;;;::::0;-1:-1:-1;;;114555:45:0;;25537:2:1;114555:45:0::2;::::0;::::2;25519:21:1::0;25576:2;25556:18;;;25549:30;-1:-1:-1;;;25595:18:1;;;25588:45;25650:18;;114555:45:0::2;25335:339:1::0;114555:45:0::2;114628:31;114753:24:::0;;;:15:::2;:24;::::0;;;;;114628:31;;114705:118:::2;::::0;114796:12;114705:29:::2;:118::i;:::-;114613:210:::0;;-1:-1:-1;114613:210:0;-1:-1:-1;114836:28:0::2;114867:37;114613:210:::0;;114867:37:::2;:::i;:::-;114966:9;::::0;114836:68;;-1:-1:-1;114938:23:0::2;114836:68:::0;114959:2:::2;114938:23;:::i;:::-;114937:38;;114915:134;;;::::0;-1:-1:-1;;;114915:134:0;;25881:2:1;114915:134:0::2;::::0;::::2;25863:21:1::0;25920:2;25900:18;;;25893:30;25959:34;25939:18;;;25932:62;-1:-1:-1;;;26010:18:1;;;26003:44;26064:19;;114915:134:0::2;25679:410:1::0;114915:134:0::2;115062:23;115271:19;;115267:2;:23;;;;:::i;:::-;115235:28;;:56;;;;:::i;:::-;115169:123;::::0;:23;:123:::2;:::i;:::-;115106:19;::::0;115102:23:::2;::::0;:2:::2;:23;:::i;:::-;115089:37;::::0;:9;:37:::2;:::i;:::-;115088:205;;;;:::i;:::-;115382:3;::::0;:25:::2;::::0;-1:-1:-1;;;115382:25:0;;115396:10:::2;115382:25;::::0;::::2;738:51:1::0;115062:231:0;;-1:-1:-1;115062:231:0;;-1:-1:-1;;;;;115382:3:0;;::::2;::::0;:13:::2;::::0;711:18:1;;115382:25:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;;115374:94;;;::::0;-1:-1:-1;;;115374:94:0;;26296:2:1;115374:94:0::2;::::0;::::2;26278:21:1::0;26335:2;26315:18;;;26308:30;26374:34;26354:18;;;26347:62;-1:-1:-1;;;26425:18:1;;;26418:35;26470:19;;115374:94:0::2;26094:401:1::0;115374:94:0::2;115494:3;::::0;:64:::2;::::0;-1:-1:-1;;;;;115494:3:0::2;115515:10;115535:4;115542:15:::0;115494:20:::2;:64::i;:::-;115602:15;115585:13;;:33;;;;:::i;:::-;115569:13;:49:::0;115665:16:::2;115684:13;:11;:13::i;:::-;115823:24;::::0;;;:15:::2;:24;::::0;;;;;;115795:25;;;;;:52;115665:32;-1:-1:-1;115891:30:0::2;115906:15:::0;115891:12;:30:::2;:::i;:::-;115858;::::0;;;:20:::2;:30;::::0;;;;;;;:63;;;;115932:12:::2;:22:::0;;;;;115957:15:::2;115932:40:::0;;116035:24;;;:15:::2;:24:::0;;;;;116028:31;;;116077:29;;;;;;116070:36;;;;116211:68;;26731:25:1;;;26772:18;;;26765:34;;;116251:10:0::2;26815:18:1::0;;;26808:60;26899:2;26884:18;;26877:34;;;116211:68:0;;::::2;::::0;;;;26718:3:1;116211:68:0;;::::2;116297:8:::0;-1:-1:-1;;;;;;87720:20:0::1;87114:1:::0;88240:7;:22;88057:213;87720:20:::1;114220:2095:::0;;;;:::o;95732:454::-;95790:7;95811:11;95824:12;95840:25;95857:7;95840:16;:25::i;:::-;95810:55;;;;95898:3;95888:7;;:13;;;;:::i;:::-;95878:7;:23;95930:13;;:19;;95946:3;;95930:19;:::i;:::-;95914:13;:35;95965:2;;:6;95962:77;;95988:21;;;;:12;:21;;;;;96012:15;95988:39;;95962:77;96118:29;;;;:20;:29;;;;;;:36;;;-1:-1:-1;96150:4:0;;95732:454;-1:-1:-1;95732:454:0:o;92635:110::-;92709:3;;:28;;-1:-1:-1;;;92709:28:0;;92731:4;92709:28;;;738:51:1;92682:7:0;;-1:-1:-1;;;;;92709:3:0;;:13;;711:18:1;;92709:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92702:35;;92635:110;:::o;111411:2349::-;111507:6;92247:16;92255:7;92247;:16::i;:::-;92239:59;;;;-1:-1:-1;;;92239:59:0;;;;;;;:::i;:::-;92317:17;;;;:8;:17;;;;;;88542:5;-1:-1:-1;92317:33:0;;;:58;;-1:-1:-1;92374:1:0;92354:17;;;:8;:17;;;;;;:21;;92317:58;92309:90;;;;-1:-1:-1;;;92309:90:0;;;;;;;:::i;:::-;111536:7:::1;92121:16;92129:7;92121;:16::i;:::-;92113:49;;;;-1:-1:-1::0;;;92113:49:0::1;;;;;;;:::i;:::-;111583:13:::2;::::0;-1:-1:-1;;;;;111583:13:0::2;:27:::0;;:58:::2;;-1:-1:-1::0;111628:13:0::2;::::0;-1:-1:-1;;;;;111628:13:0::2;111614:10;:27;111583:58;111561:142;;;::::0;-1:-1:-1;;;111561:142:0;;27124:2:1;111561:142:0::2;::::0;::::2;27106:21:1::0;27163:2;27143:18;;;27136:30;27202:34;27182:18;;;27175:62;-1:-1:-1;;;27253:18:1;;;27246:32;27295:19;;111561:142:0::2;26922:398:1::0;111561:142:0::2;111716:20;111739:24;111755:7;111739:15;:24::i;:::-;111789:31;111914:24:::0;;;:15:::2;:24;::::0;;;;;111716:47;;-1:-1:-1;111789:31:0;;;111866:118:::2;::::0;111716:47;111866:29:::2;:118::i;:::-;111774:210;;;;112003:12;112019:1;112003:17;;111995:45;;;::::0;-1:-1:-1;;;111995:45:0;;25537:2:1;111995:45:0::2;::::0;::::2;25519:21:1::0;25576:2;25556:18;;;25549:30;-1:-1:-1;;;25595:18:1;;;25588:45;25650:18;;111995:45:0::2;25335:339:1::0;111995:45:0::2;112053:28;112084:37;112111:9:::0;112084:23;:37:::2;:::i;:::-;112053:68;;112179:28;;112156:20;:51;112134:149;;;::::0;-1:-1:-1;;;112134:149:0;;27527:2:1;112134:149:0::2;::::0;::::2;27509:21:1::0;27566:2;27546:18;;;27539:30;27605:34;27585:18;;;27578:62;-1:-1:-1;;;27656:18:1;;;27649:46;27712:19;;112134:149:0::2;27325:412:1::0;112134:149:0::2;112332:9;::::0;112304:25:::2;:20:::0;112327:2:::2;112304:25;:::i;:::-;:37;112296:80;;;::::0;-1:-1:-1;;;112296:80:0;;27944:2:1;112296:80:0::2;::::0;::::2;27926:21:1::0;27983:2;27963:18;;;27956:30;28022:31;28002:18;;;27995:59;28071:18;;112296:80:0::2;27742:353:1::0;112296:80:0::2;112418:19;::::0;112414:23:::2;::::0;:2:::2;:23;:::i;:::-;112401:37;::::0;:9;:37:::2;:::i;:::-;112389:49;;112451:16;112483:9;;112470;:23;;;;:::i;:::-;112451:42;;112538:7;;112526:8;:19;112522:72;;-1:-1:-1::0;112573:9:0;112522:72:::2;112628:3;::::0;:25:::2;::::0;-1:-1:-1;;;112628:25:0;;112642:10:::2;112628:25;::::0;::::2;738:51:1::0;112657:8:0;;-1:-1:-1;;;;;112628:3:0::2;::::0;:13:::2;::::0;711:18:1;;112628:25:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:37;;112606:136;;;::::0;-1:-1:-1;;;112606:136:0;;28302:2:1;112606:136:0::2;::::0;::::2;28284:21:1::0;28341:2;28321:18;;;28314:30;28380:34;28360:18;;;28353:62;-1:-1:-1;;;28431:18:1;;;28424:47;28488:19;;112606:136:0::2;28100:413:1::0;112606:136:0::2;112788:8;112771:13;;:26;;;;:::i;:::-;112755:13;:42:::0;112810:20:::2;112833:21;112846:7:::0;112833:12:::2;:21::i;:::-;112810:44:::0;-1:-1:-1;112899:25:0::2;112915:8:::0;112899:12;:25:::2;:::i;:::-;112867:29;::::0;;;:20:::2;:29;::::0;;;;;;;:57;;;;113006:10:::2;::::0;113028:16;;;:8:::2;:16:::0;;;;;;;112867:29;;112993:52:::2;::::0;113018:8;;112993:12:::2;:52::i;:::-;113083:24;::::0;;;:15:::2;:24;::::0;;;;;112971:74;;-1:-1:-1;113083:40:0::2;::::0;112971:74;;113083:40:::2;:::i;:::-;113056:24;::::0;;;:15:::2;:24;::::0;;;;;:67;;;;113160:23;;;;;:39:::2;::::0;113187:11;;113160:39:::2;:::i;:::-;113134:23;::::0;;;:15:::2;:23;::::0;;;;;:65;;;;113307:24;;;;;:41:::2;::::0;113335:12;;113307:41:::2;:::i;:::-;113280:24;::::0;;;:15:::2;:24;::::0;;;;;;;:68;;;;113442:10:::2;113432:21:::0;;:9:::2;:21:::0;;;;:38:::2;::::0;113457:12;;113432:38:::2;:::i;:::-;113418:10;113408:21;::::0;;;:9:::2;:21;::::0;;;;:62;;;;113498:3:::2;::::0;:57:::2;::::0;-1:-1:-1;;;;;113498:3:0;;::::2;::::0;113539:4:::2;113546:8:::0;113498:20:::2;:57::i;:::-;113573:179;113602:7;113624:16;113632:7;113624;:16::i;:::-;113573:179;::::0;;28805:25:1;;;-1:-1:-1;;;;;28904:15:1;;;28899:2;28884:18;;28877:43;113655:10:0::2;28936:18:1::0;;;28929:43;29003:2;28988:18;;28981:34;;;29046:3;29031:19;;29024:35;;;28857:3;29075:19;;29068:35;;;28792:3;28777:19;113573:179:0::2;;;;;;;111550:2210;;;;;;;92410:1:::1;111411:2349:::0;;;:::o;37054:104::-;37110:13;37143:7;37136:14;;;;;:::i;102211:1365::-;102342:6;92247:16;92255:7;92247;:16::i;:::-;92239:59;;;;-1:-1:-1;;;92239:59:0;;;;;;;:::i;:::-;92317:17;;;;:8;:17;;;;;;88542:5;-1:-1:-1;92317:33:0;;;:58;;-1:-1:-1;92374:1:0;92354:17;;;:8;:17;;;;;;:21;;92317:58;92309:90;;;;-1:-1:-1;;;92309:90:0;;;;;;;:::i;:::-;102371:7:::1;91746:16;91754:7;91746;:16::i;:::-;91738:49;;;;-1:-1:-1::0;;;91738:49:0::1;;;;;;;:::i;:::-;91826:10;91806:16;91814:7:::0;91806::::1;:16::i;:::-;-1:-1:-1::0;;;;;91806:30:0::1;;91798:68;;;;-1:-1:-1::0;;;91798:68:0::1;;;;;;;:::i;:::-;87676:21:::2;:19;:21::i;:::-;102434:1:::3;102425:6;:10;102417:50;;;::::0;-1:-1:-1;;;102417:50:0;;29316:2:1;102417:50:0::3;::::0;::::3;29298:21:1::0;29355:2;29335:18;;;29328:30;29394:29;29374:18;;;29367:57;29441:18;;102417:50:0::3;29114:351:1::0;102417:50:0::3;102510:16;:14;:16::i;:::-;102500:6;:26;;102478:123;;;::::0;-1:-1:-1;;;102478:123:0;;29672:2:1;102478:123:0::3;::::0;::::3;29654:21:1::0;29711:2;29691:18;;;29684:30;29750:34;29730:18;;;29723:62;-1:-1:-1;;;29801:18:1;;;29794:45;29856:19;;102478:123:0::3;29470:411:1::0;102478:123:0::3;102614:15;102659:6;102632:24;102648:7;102632:15;:24::i;:::-;:33;;;;:::i;:::-;102614:51;;102695:7;;102686;:16;;102678:63;;;::::0;-1:-1:-1;;;102678:63:0;;30088:2:1;102678:63:0::3;::::0;::::3;30070:21:1::0;30127:2;30107:18;;;30100:30;30166:34;30146:18;;;30139:62;-1:-1:-1;;;30217:18:1;;;30210:32;30259:19;;102678:63:0::3;29886:398:1::0;102678:63:0::3;102772:18;102782:7;102772:9;:18::i;:::-;102762:7;:28;102754:37;;;::::0;::::3;;102846:24;::::0;;;:15:::3;:24;::::0;;;;;102828:52:::3;::::0;102872:7;102828:17:::3;:52::i;:::-;102806:160;;;::::0;-1:-1:-1;;;102806:160:0;;30491:2:1;102806:160:0::3;::::0;::::3;30473:21:1::0;30530:2;30510:18;;;30503:30;30569:34;30549:18;;;30542:62;30640:28;30620:18;;;30613:56;30686:19;;102806:160:0::3;30289:422:1::0;102806:160:0::3;103036:7;;103025:6;103003:18;103013:7;103003:9;:18::i;:::-;103002:29;;;;:::i;:::-;103001:42;;102979:125;;;;-1:-1:-1::0;;;102979:125:0::3;;;;;;;:::i;:::-;103117:29;::::0;;;:20:::3;:29;::::0;;;;;;;:39;;;103204:10:::3;::::0;103225:16;;;:8:::3;:16:::0;;;;;;103191:51:::3;::::0;103204:10;103149:7;;103191:12:::3;:51::i;:::-;103282:24;::::0;;;:15:::3;:24;::::0;;;;;103169:73;;-1:-1:-1;103282:40:0::3;::::0;103169:73;;103282:40:::3;:::i;:::-;103255:24;::::0;;;:15:::3;:24;::::0;;;;;:67;;;;103359:23;;;;;:39:::3;::::0;103386:11;;103359:39:::3;:::i;:::-;103333:23;::::0;;;:15:::3;:23;::::0;;;;:65;103435:3:::3;::::0;:36:::3;::::0;-1:-1:-1;;;;;103435:3:0::3;103452:10;103464:6:::0;103435:16:::3;:36::i;:::-;103515:6;103498:13;;:24;;;;:::i;:::-;103482:13;:40:::0;103540:28:::3;::::0;;11659:25:1;;;11715:2;11700:18;;11693:34;;;103540:28:0::3;::::0;11632:18:1;103540:28:0::3;;;;;;;102404:1172;;87720:20:::2;87114:1:::0;88240:7;:22;88057:213;87720:20:::2;92410:1:::1;102211:1365:::0;;;;:::o;94150:114::-;94227:14;;:29;;;-1:-1:-1;;;94227:29:0;;;;94200:7;;-1:-1:-1;;;;;94227:14:0;;:27;;:29;;;;;;;;;;;;;;:14;:29;;;;;;;;;;;;;;123300:231;117447:13;:11;:13::i;:::-;-1:-1:-1;;;;;123379:19:0;::::1;123371:69;;;::::0;-1:-1:-1;;;123371:69:0;;30918:2:1;123371:69:0::1;::::0;::::1;30900:21:1::0;30957:2;30937:18;;;30930:30;30996:34;30976:18;;;30969:62;-1:-1:-1;;;31047:18:1;;;31040:34;31091:19;;123371:69:0::1;30716:400:1::0;123371:69:0::1;123451:13;:21:::0;;-1:-1:-1;;;;;;123451:21:0::1;-1:-1:-1::0;;;;;123451:21:0;::::1;::::0;;::::1;::::0;;;123488:35:::1;::::0;738:51:1;;;123488:35:0::1;::::0;726:2:1;711:18;123488:35:0::1;592:203:1::0;38640:155:0;38735:52;11322:10;38768:8;38778;38735:18;:52::i;121486:149::-;117447:13;:11;:13::i;:::-;121565:20;;::::1;::::0;:10:::1;::::0;:20:::1;::::0;::::1;::::0;::::1;:::i;:::-;;121601:26;121619:7;121601:26;;;;;;:::i;93237:252::-:0;93373:10;;:35;;-1:-1:-1;;;93373:35:0;;93402:4;93373:35;;;738:51:1;93291:7:0;;-1:-1:-1;;;;;93373:10:0;;:20;;711:18:1;;93373:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93342:28;;93320:19;:17;:19::i;:::-;:50;;;;:::i;:::-;:88;;;;:::i;110310:702::-;110394:4;110376:7;92121:16;92129:7;92121;:16::i;:::-;92113:49;;;;-1:-1:-1;;;92113:49:0;;;;;;;:::i;:::-;110413:20:::1;110436:18;110446:7;110436:9;:18::i;:::-;110471:24;::::0;;;:15:::1;:24;::::0;;;;;110413:41;;-1:-1:-1;110471:29:0;;:50:::1;;-1:-1:-1::0;110504:17:0;;110471:50:::1;110467:95;;;110545:5;110538:12;;;;;110467:95;110589:31;110714:24:::0;;;:15:::1;:24;::::0;;;;;110589:31;;110666:118:::1;::::0;110757:12;110666:29:::1;:118::i;:::-;110574:210:::0;;-1:-1:-1;110574:210:0;-1:-1:-1;110797:28:0::1;110828:37;110574:210:::0;;110828:37:::1;:::i;:::-;110911:9;::::0;110797:68;;-1:-1:-1;110883:23:0::1;110797:68:::0;110904:2:::1;110883:23;:::i;:::-;110882:38;110878:127;;110944:4;110937:11;;;;;;;;110878:127;110988:5;110981:12;;;;;;;;109358:753:::0;109479:4;109452:7;92121:16;92129:7;92121;:16::i;:::-;92113:49;;;;-1:-1:-1;;;92113:49:0;;;;;;;:::i;:::-;109501:20:::1;109524:18;109534:7;109524:9;:18::i;:::-;109559:24;::::0;;;:15:::1;:24;::::0;;;;;109501:41;;-1:-1:-1;109559:29:0;;:50:::1;;-1:-1:-1::0;109592:17:0;;109559:50:::1;109555:95;;;109633:5;109626:12;;;;;109555:95;109677:31;109802:24:::0;;;:15:::1;:24;::::0;;;;;109677:31;;109754:118:::1;::::0;109845:12;109754:29:::1;:118::i;:::-;109662:210:::0;;-1:-1:-1;109662:210:0;-1:-1:-1;109885:28:0::1;109916:37;109662:210:::0;;109916:37:::1;:::i;:::-;109885:68;;109991:28;;109968:20;:51;109964:140;;;110043:4;110036:11;;;;;;;;39759:322:::0;39933:41;11322:10;39966:7;39933:18;:41::i;:::-;39925:99;;;;-1:-1:-1;;;39925:99:0;;;;;;;:::i;:::-;40035:38;40049:4;40055:2;40059:7;40068:4;40035:13;:38::i;:::-;39759:322;;;;:::o;129983:125::-;117447:13;:11;:13::i;:::-;130049:6:::1;:14:::0;;-1:-1:-1;;;;;;130049:14:0::1;-1:-1:-1::0;;;;;130049:14:0;::::1;::::0;;::::1;::::0;;;130079:21:::1;::::0;738:51:1;;;130079:21:0::1;::::0;726:2:1;711:18;130079:21:0::1;592:203:1::0;60807:370:0;60880:13;60906:23;60921:7;60906:14;:23::i;:::-;60942:21;60966:10;:8;:10::i;:::-;60990:6;;60942:34;;-1:-1:-1;60990:6:0;;60987:183;;;61043:1;61025:7;61019:21;:25;:93;;;;;;;;;;;;;;;;;61071:7;61080:25;61097:7;61080:16;:25::i;:::-;61054:52;;;;;;;;;:::i;:::-;;;;;;;;;;;;;61019:93;61012:100;60807:370;-1:-1:-1;;;60807:370:0:o;127776:311::-;127858:9;92247:16;92255:7;92247;:16::i;:::-;92239:59;;;;-1:-1:-1;;;92239:59:0;;;;;;;:::i;:::-;92317:17;;;;:8;:17;;;;;;88542:5;-1:-1:-1;92317:33:0;;;:58;;-1:-1:-1;92374:1:0;92354:17;;;:8;:17;;;;;;:21;;92317:58;92309:90;;;;-1:-1:-1;;;92309:90:0;;;;;;;:::i;:::-;127884:9:::1;91746:16;91754:7;91746;:16::i;:::-;91738:49;;;;-1:-1:-1::0;;;91738:49:0::1;;;;;;;:::i;:::-;91826:10;91806:16;91814:7:::0;91806::::1;:16::i;:::-;-1:-1:-1::0;;;;;91806:30:0::1;;91798:68;;;;-1:-1:-1::0;;;91798:68:0::1;;;;;;;:::i;:::-;127925:1:::2;127914:8;:12;:40;;;;;88542:5;127930:8;:24;;127914:40;127906:80;;;::::0;-1:-1:-1;;;127906:80:0;;31798:2:1;127906:80:0::2;::::0;::::2;31780:21:1::0;31837:2;31817:18;;;31810:30;31876:29;31856:18;;;31849:57;31923:18;;127906:80:0::2;31596:351:1::0;127906:80:0::2;127997:19;::::0;;;:8:::2;:19;::::0;;;;;;;;:30;;;128043:36;;11659:25:1;;;11700:18;;;11693:34;;;128043:36:0::2;::::0;11632:18:1;128043:36:0::2;;;;;;;;92410:1:::1;127776:311:::0;;;:::o;105595:266::-;87676:21;:19;:21::i;:::-;105665:10:::1;105655:21;::::0;;;:9:::1;:21;::::0;;;;;105647:67:::1;;;::::0;-1:-1:-1;;;105647:67:0;;21383:2:1;105647:67:0::1;::::0;::::1;21365:21:1::0;21422:2;21402:18;;;21395:30;21461;21441:18;;;21434:58;21509:18;;105647:67:0::1;21181:352:1::0;105647:67:0::1;105752:10;105725:14;105742:21:::0;;;:9:::1;:21;::::0;;;;;;105774:25;;;105810:10:::1;::::0;105742:21;;105810:43:::1;::::0;-1:-1:-1;;;;;105810:10:0::1;::::0;105742:21;105810:23:::1;:43::i;:::-;105636:225;87720:20:::0;87114:1;88240:7;:22;88057:213;103584:405;103715:6;92247:16;92255:7;92247;:16::i;:::-;92239:59;;;;-1:-1:-1;;;92239:59:0;;;;;;;:::i;:::-;92317:17;;;;:8;:17;;;;;;88542:5;-1:-1:-1;92317:33:0;;;:58;;-1:-1:-1;92374:1:0;92354:17;;;:8;:17;;;;;;:21;;92317:58;92309:90;;;;-1:-1:-1;;;92309:90:0;;;;;;;:::i;:::-;103735:7:::1;92121:16;92129:7;92121;:16::i;:::-;92113:49;;;;-1:-1:-1::0;;;92113:49:0::1;;;;;;;:::i;:::-;91949:6:::2;::::0;-1:-1:-1;;;;;91949:6:0::2;:20:::0;;:44:::2;;-1:-1:-1::0;91987:6:0::2;::::0;-1:-1:-1;;;;;91987:6:0::2;91973:10;:20;91949:44;91927:109;;;;-1:-1:-1::0;;;91927:109:0::2;;;;;;;:::i;:::-;103800:15:::3;103788:8;:27;;103766:111;;;::::0;-1:-1:-1;;;103766:111:0;;32154:2:1;103766:111:0::3;::::0;::::3;32136:21:1::0;32193:2;32173:18;;;32166:30;32232:34;32212:18;;;32205:62;-1:-1:-1;;;32283:18:1;;;32276:32;32325:19;;103766:111:0::3;31952:398:1::0;103766:111:0::3;103890:15;103908:24;103924:7;103908:15;:24::i;:::-;103890:42;;103943:38;103956:7;103965;103974:6;103943:12;:38::i;:::-;103755:234;92410:1:::1;103584:405:::0;;;;:::o;95375:151::-;95432:7;95455:12;95471:25;95488:7;95471:16;:25::i;108578:585::-;108708:7;108681;92121:16;92129:7;92121;:16::i;:::-;92113:49;;;;-1:-1:-1;;;92113:49:0;;;;;;;:::i;:::-;108733:20:::1;108756:18;108766:7;108756:9;:18::i;:::-;108791:24;::::0;;;:15:::1;:24;::::0;;;;;108733:41;;-1:-1:-1;108791:29:0;;:50:::1;;-1:-1:-1::0;108824:17:0;;108791:50:::1;108787:91;;;108865:1;108858:8;;;;;108787:91;108903:31;109028:24:::0;;;:15:::1;:24;::::0;;;;;108903:31;;108980:118:::1;::::0;109071:12;108980:29:::1;:118::i;:::-;108888:210:::0;;-1:-1:-1;108888:210:0;-1:-1:-1;109118:37:0::1;108888:210:::0;;109118:37:::1;:::i;:::-;109111:44:::0;108578:585;-1:-1:-1;;;;;;108578:585:0:o;129832:143::-;117447:13;:11;:13::i;:::-;129909:18:::1;:7;129919:8:::0;;129909:18:::1;:::i;:::-;;129943:24;129959:7;129943:24;;;;;;:::i;122257:206::-:0;117447:13;:11;:13::i;:::-;122337:15;122329:50:::1;;;::::0;-1:-1:-1;;;122329:50:0;;33874:2:1;122329:50:0::1;::::0;::::1;33856:21:1::0;33913:2;33893:18;;;33886:30;-1:-1:-1;;;33932:18:1;;;33925:52;33994:18;;122329:50:0::1;33672:346:1::0;122329:50:0::1;122390:9;:22:::0;;;122428:27:::1;::::0;2918:25:1;;;122428:27:0::1;::::0;2906:2:1;2891:18;122428:27:0::1;2772:177:1::0;100327:454:0;100426:7;92121:16;92129:7;92121;:16::i;:::-;92113:49;;;;-1:-1:-1;;;92113:49:0;;;;;;;:::i;:::-;91949:6:::1;::::0;-1:-1:-1;;;;;91949:6:0::1;:20:::0;;:44:::1;;-1:-1:-1::0;91987:6:0::1;::::0;-1:-1:-1;;;;;91987:6:0::1;91973:10;:20;91949:44;91927:109;;;;-1:-1:-1::0;;;91927:109:0::1;;;;;;;:::i;:::-;100471:21:::2;100495:24:::0;;;:15:::2;:24;::::0;;;;;:35:::2;::::0;100523:6;;100495:35:::2;:::i;:::-;100568:24;::::0;;;:15:::2;:24;::::0;;;;;100471:59;;-1:-1:-1;100551:41:0;::::2;;100543:50;;;::::0;::::2;;100606:24;::::0;;;:15:::2;:24;::::0;;;;:40;;;100659:10:::2;::::0;:62:::2;::::0;-1:-1:-1;;;;;100659:10:0::2;100687;100707:4;100714:6:::0;100659:27:::2;:62::i;:::-;100739:34;::::0;;11659:25:1;;;11715:2;11700:18;;11693:34;;;100739::0::2;::::0;11632:18:1;100739:34:0::2;11485:248:1::0;118467:201:0;117447:13;:11;:13::i;:::-;-1:-1:-1;;;;;118556:22:0;::::1;118548:73;;;::::0;-1:-1:-1;;;118548:73:0;;34225:2:1;118548:73:0::1;::::0;::::1;34207:21:1::0;34264:2;34244:18;;;34237:30;34303:34;34283:18;;;34276:62;-1:-1:-1;;;34354:18:1;;;34347:36;34400:19;;118548:73:0::1;34023:402:1::0;118548:73:0::1;118632:28;118651:8;118632:18;:28::i;121832:233::-:0;117447:13;:11;:13::i;:::-;121926:4:::1;121912:10;:18;;121904:77;;;::::0;-1:-1:-1;;;121904:77:0;;34632:2:1;121904:77:0::1;::::0;::::1;34614:21:1::0;34671:2;34651:18;;;34644:30;34710:34;34690:18;;;34683:62;-1:-1:-1;;;34761:18:1;;;34754:44;34815:19;;121904:77:0::1;34430:410:1::0;121904:77:0::1;121992:9;:22:::0;;;122030:27:::1;::::0;2918:25:1;;;122030:27:0::1;::::0;2906:2:1;2891:18;122030:27:0::1;2772:177:1::0;55048:915:0;55225:61;55252:4;55258:2;55262:12;55276:9;55225:26;:61::i;:::-;55315:1;55303:9;:13;55299:222;;;55446:63;;-1:-1:-1;;;55446:63:0;;35047:2:1;55446:63:0;;;35029:21:1;35086:2;35066:18;;;35059:30;35125:34;35105:18;;;35098:62;-1:-1:-1;;;35176:18:1;;;35169:51;35237:19;;55446:63:0;34845:417:1;55299:222:0;55551:12;-1:-1:-1;;;;;55580:18:0;;55576:187;;55615:40;55647:7;56790:10;:17;;56763:24;;;;:15;:24;;;;;:44;;;56818:24;;;;;;;;;;;;56686:164;55615:40;55576:187;;;55685:2;-1:-1:-1;;;;;55677:10:0;:4;-1:-1:-1;;;;;55677:10:0;;55673:90;;55704:47;55737:4;55743:7;55704:32;:47::i;:::-;-1:-1:-1;;;;;55777:16:0;;55773:183;;55810:45;55847:7;55810:36;:45::i;:::-;55773:183;;;55883:4;-1:-1:-1;;;;;55877:10:0;:2;-1:-1:-1;;;;;55877:10:0;;55873:83;;55904:40;55932:2;55936:7;55904:27;:40::i;50500:410::-;50690:1;50678:9;:13;50674:229;;;-1:-1:-1;;;;;50712:18:0;;;50708:87;;-1:-1:-1;;;;;50751:15:0;;;;;;:9;:15;;;;;:28;;50770:9;;50751:15;:28;;50770:9;;50751:28;:::i;:::-;;;;-1:-1:-1;;50708:87:0;-1:-1:-1;;;;;50813:16:0;;;50809:83;;-1:-1:-1;;;;;50850:13:0;;;;;;:9;:13;;;;;:26;;50867:9;;50850:13;:26;;50867:9;;50850:26;:::i;:::-;;;;-1:-1:-1;;50500:410:0;;;;:::o;87756:293::-;87158:1;87890:7;;:19;;87882:63;;;;-1:-1:-1;;;87882:63:0;;35469:2:1;87882:63:0;;;35451:21:1;35508:2;35488:18;;;35481:30;35547:33;35527:18;;;35520:61;35598:18;;87882:63:0;35267:355:1;87882:63:0;87158:1;88023:7;:18;87756:293::o;53911:224::-;54013:4;-1:-1:-1;;;;;;54037:50:0;;-1:-1:-1;;;54037:50:0;;:90;;;54091:36;54115:11;54091:23;:36::i;117726:132::-;117634:6;;-1:-1:-1;;;;;117634:6:0;11322:10;117790:23;117782:68;;;;-1:-1:-1;;;117782:68:0;;35829:2:1;117782:68:0;;;35811:21:1;;;35848:18;;;35841:30;35907:34;35887:18;;;35880:62;35959:18;;117782:68:0;35627:356:1;48216:135:0;48298:16;48306:7;48298;:16::i;:::-;48290:53;;;;-1:-1:-1;;;48290:53:0;;21030:2:1;48290:53:0;;;21012:21:1;21069:2;21049:18;;;21042:30;-1:-1:-1;;;21088:18:1;;;21081:54;21152:18;;48290:53:0;20828:348:1;47495:174:0;47570:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;47570:29:0;-1:-1:-1;;;;;47570:29:0;;;;;;;;:24;;47624:23;47570:24;47624:14;:23::i;:::-;-1:-1:-1;;;;;47615:46:0;;;;;;;;;;;47495:174;;:::o;96549:713::-;96673:7;96682;96715:19;:17;:19::i;:::-;96707:33;;;;;;96799:23;96887:28;;96852:19;:17;:19::i;:::-;96825:46;;:11;:46;:::i;:::-;:90;;;;:::i;:::-;96799:116;;96955:11;96936:15;:30;;96928:39;;;;;;96980:17;97000:29;88932:3;97000:5;:29;:::i;:::-;96980:49;;97063:5;97050:9;:18;;97042:27;;;;;;97082:31;97116:21;:15;97134:3;97116:21;:::i;:::-;97082:55;;97182:15;97156:23;:41;97148:50;;;;;;97219:23;97244:9;;-1:-1:-1;96549:713:0;-1:-1:-1;;;;96549:713:0:o;42114:264::-;42207:4;42224:13;42240:23;42255:7;42240:14;:23::i;:::-;42224:39;;42293:5;-1:-1:-1;;;;;42282:16:0;:7;-1:-1:-1;;;;;42282:16:0;;:52;;;-1:-1:-1;;;;;;38987:25:0;;;38963:4;38987:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;42302:32;42282:87;;;;42362:7;-1:-1:-1;;;;;42338:31:0;:20;42350:7;42338:11;:20::i;:::-;-1:-1:-1;;;;;42338:31:0;;42274:96;42114:264;-1:-1:-1;;;;42114:264:0:o;46113:1263::-;46272:4;-1:-1:-1;;;;;46245:31:0;:23;46260:7;46245:14;:23::i;:::-;-1:-1:-1;;;;;46245:31:0;;46237:81;;;;-1:-1:-1;;;46237:81:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;46337:16:0;;46329:65;;;;-1:-1:-1;;;46329:65:0;;36596:2:1;46329:65:0;;;36578:21:1;36635:2;36615:18;;;36608:30;36674:34;36654:18;;;36647:62;-1:-1:-1;;;36725:18:1;;;36718:34;36769:19;;46329:65:0;36394:400:1;46329:65:0;46407:42;46428:4;46434:2;46438:7;46447:1;46407:20;:42::i;:::-;46579:4;-1:-1:-1;;;;;46552:31:0;:23;46567:7;46552:14;:23::i;:::-;-1:-1:-1;;;;;46552:31:0;;46544:81;;;;-1:-1:-1;;;46544:81:0;;;;;;;:::i;:::-;46697:24;;;;:15;:24;;;;;;;;46690:31;;-1:-1:-1;;;;;;46690:31:0;;;;;;-1:-1:-1;;;;;47173:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;47173:20:0;;;47208:13;;;;;;;;;:18;;46690:31;47208:18;;;47248:16;;;:7;:16;;;;;;:21;;;;;;;;;;47287:27;;46713:7;;47287:27;;;37985:346;37915:416;;:::o;41819:128::-;41884:4;41482:16;;;:7;:16;;;;;;-1:-1:-1;;;;;41482:16:0;41908:31;;;41819:128::o;67679:248::-;67850:68;;-1:-1:-1;;;;;37057:15:1;;;67850:68:0;;;37039:34:1;37109:15;;37089:18;;;37082:43;37141:18;;;37134:34;;;67823:96:0;;67843:5;;-1:-1:-1;;;67873:27:0;36974:18:1;;67850:68:0;;;;-1:-1:-1;;67850:68:0;;;;;;;;;;;;;;-1:-1:-1;;;;;67850:68:0;-1:-1:-1;;;;;;67850:68:0;;;;;;;;;;67823:19;:96::i;43712:942::-;-1:-1:-1;;;;;43792:16:0;;43784:61;;;;-1:-1:-1;;;43784:61:0;;37381:2:1;43784:61:0;;;37363:21:1;;;37400:18;;;37393:30;37459:34;37439:18;;;37432:62;37511:18;;43784:61:0;37179:356:1;43784:61:0;43865:16;43873:7;43865;:16::i;:::-;43864:17;43856:58;;;;-1:-1:-1;;;43856:58:0;;37742:2:1;43856:58:0;;;37724:21:1;37781:2;37761:18;;;37754:30;37820;37800:18;;;37793:58;37868:18;;43856:58:0;37540:352:1;43856:58:0;43927:48;43956:1;43960:2;43964:7;43973:1;43927:20;:48::i;:::-;44074:16;44082:7;44074;:16::i;:::-;44073:17;44065:58;;;;-1:-1:-1;;;44065:58:0;;37742:2:1;44065:58:0;;;37724:21:1;37781:2;37761:18;;;37754:30;37820;37800:18;;;37793:58;37868:18;;44065:58:0;37540:352:1;44065:58:0;-1:-1:-1;;;;;44472:13:0;;;;;;:9;:13;;;;;;;;:18;;44489:1;44472:18;;;44514:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;44514:21:0;;;;;44553:33;44522:7;;44472:13;;44553:33;;44472:13;;44553:33;99471:578;;:::o;67460:211::-;67604:58;;-1:-1:-1;;;;;9037:32:1;;67604:58:0;;;9019:51:1;9086:18;;;9079:34;;;67577:86:0;;67597:5;;-1:-1:-1;;;67627:23:0;8992:18:1;;67604:58:0;8845:274:1;118828:191:0;118921:6;;;-1:-1:-1;;;;;118938:17:0;;;-1:-1:-1;;;;;;118938:17:0;;;;;;;118971:40;;118921:6;;;118938:17;118921:6;;118971:40;;118902:16;;118971:40;118891:128;118828:191;:::o;44993:783::-;45053:13;45069:23;45084:7;45069:14;:23::i;:::-;45053:39;;45105:51;45126:5;45141:1;45145:7;45154:1;45105:20;:51::i;:::-;45269:23;45284:7;45269:14;:23::i;:::-;45340:24;;;;:15;:24;;;;;;;;45333:31;;-1:-1:-1;;;;;;45333:31:0;;;;;;-1:-1:-1;;;;;45585:16:0;;;;;:9;:16;;;;;:21;;-1:-1:-1;;45585:21:0;;;45635:16;;;:7;:16;;;;;;45628:23;;;;;;;45669:36;45261:31;;-1:-1:-1;45356:7:0;;45669:36;;45340:24;;45669:36;99471:578;;:::o;94566:577::-;94659:7;94756:29;;;:20;:29;;;;;;;;;94826:12;:21;;;;;;94659:7;;94715:15;;94659:7;;94826:26;;;;:36;;;94861:1;94856:2;;:6;94826:36;94822:285;;;94879:17;94913:21;;;:12;:21;;;;;;94899:35;;:11;:35;:::i;:::-;94879:55;;94951:18;88542:5;88582:8;94988:9;94980:4;94975:2;;:9;;;;:::i;:::-;94974:23;;;;:::i;:::-;94973:36;;;;:::i;:::-;94972:53;;;;:::i;:::-;94951:74;-1:-1:-1;94951:74:0;;-1:-1:-1;95078:17:0;95091:4;94951:74;95078:17;:::i;:::-;95071:24;;94864:243;;94822:285;95125:3;95130:4;;-1:-1:-1;94566:577:0;-1:-1:-1;;;94566:577:0:o;47812:315::-;47967:8;-1:-1:-1;;;;;47958:17:0;:5;-1:-1:-1;;;;;47958:17:0;;;47950:55;;;;-1:-1:-1;;;47950:55:0;;38099:2:1;47950:55:0;;;38081:21:1;38138:2;38118:18;;;38111:30;38177:27;38157:18;;;38150:55;38222:18;;47950:55:0;37897:349:1;47950:55:0;-1:-1:-1;;;;;48016:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;48016:46:0;;;;;;;;;;48078:41;;540::1;;;48078::0;;513:18:1;48078:41:0;;;;;;;47812:315;;;:::o;40962:313::-;41118:28;41128:4;41134:2;41138:7;41118:9;:28::i;:::-;41165:47;41188:4;41194:2;41198:7;41207:4;41165:22;:47::i;:::-;41157:110;;;;-1:-1:-1;;;41157:110:0;;;;;;;:::i;60628:108::-;60688:13;60721:7;60714:14;;;;;:::i;30802:716::-;30858:13;30909:14;30926:17;30937:5;30926:10;:17::i;:::-;30946:1;30926:21;30909:38;;30962:20;30996:6;30985:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;30985:18:0;-1:-1:-1;30962:41:0;-1:-1:-1;31127:28:0;;;31143:2;31127:28;31184:288;-1:-1:-1;;31216:5:0;-1:-1:-1;;;31353:2:0;31342:14;;31337:30;31216:5;31324:44;31414:2;31405:11;;;-1:-1:-1;31439:10:0;31435:21;;31451:5;;31435:21;31184:288;;;-1:-1:-1;31493:6:0;30802:716;-1:-1:-1;;;30802:716:0:o;57477:988::-;57743:22;57793:1;57768:22;57785:4;57768:16;:22::i;:::-;:26;;;;:::i;:::-;57805:18;57826:26;;;:17;:26;;;;;;57743:51;;-1:-1:-1;57959:28:0;;;57955:328;;-1:-1:-1;;;;;58026:18:0;;58004:19;58026:18;;;:12;:18;;;;;;;;:34;;;;;;;;;58077:30;;;;;;:44;;;58194:30;;:17;:30;;;;;:43;;;57955:328;-1:-1:-1;58379:26:0;;;;:17;:26;;;;;;;;58372:33;;;-1:-1:-1;;;;;58423:18:0;;;;;:12;:18;;;;;:34;;;;;;;58416:41;57477:988::o;58760:1079::-;59038:10;:17;59013:22;;59038:21;;59058:1;;59038:21;:::i;:::-;59070:18;59091:24;;;:15;:24;;;;;;59464:10;:26;;59013:46;;-1:-1:-1;59091:24:0;;59013:46;;59464:26;;;;;;:::i;:::-;;;;;;;;;59442:48;;59528:11;59503:10;59514;59503:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;59608:28;;;:15;:28;;;;;;;:41;;;59780:24;;;;;59773:31;59815:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;58831:1008;;;58760:1079;:::o;56264:221::-;56349:14;56366:20;56383:2;56366:16;:20::i;:::-;-1:-1:-1;;;;;56397:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;56442:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;56264:221:0:o;35957:305::-;36059:4;-1:-1:-1;;;;;;36096:40:0;;-1:-1:-1;;;36096:40:0;;:105;;-1:-1:-1;;;;;;;36153:48:0;;-1:-1:-1;;;36153:48:0;36096:105;:158;;;-1:-1:-1;;;;;;;;;;34491:40:0;;;36218:36;34382:157;60072:211;60219:56;60246:4;60252:2;60256:7;60265:9;60219:26;:56::i;70527:716::-;70951:23;70977:69;71005:4;70977:69;;;;;;;;;;;;;;;;;70985:5;-1:-1:-1;;;;;70977:27:0;;;:69;;;;;:::i;:::-;71061:17;;70951:95;;-1:-1:-1;71061:21:0;71057:179;;71158:10;71147:30;;;;;;;;;;;;:::i;:::-;71139:85;;;;-1:-1:-1;;;71139:85:0;;39004:2:1;71139:85:0;;;38986:21:1;39043:2;39023:18;;;39016:30;39082:34;39062:18;;;39055:62;-1:-1:-1;;;39133:18:1;;;39126:40;39183:19;;71139:85:0;38802:406:1;48915:853:0;49069:4;-1:-1:-1;;;;;49090:13:0;;1597:19;:23;49086:675;;49126:71;;-1:-1:-1;;;49126:71:0;;-1:-1:-1;;;;;49126:36:0;;;;;:71;;11322:10;;49177:4;;49183:7;;49192:4;;49126:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49126:71:0;;;;;;;;-1:-1:-1;;49126:71:0;;;;;;;;;;;;:::i;:::-;;;49122:584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49367:13:0;;49363:328;;49410:60;;-1:-1:-1;;;49410:60:0;;;;;;;:::i;49363:328::-;49641:6;49635:13;49626:6;49622:2;49618:15;49611:38;49122:584;-1:-1:-1;;;;;;49248:51:0;-1:-1:-1;;;49248:51:0;;-1:-1:-1;49241:58:0;;49086:675;-1:-1:-1;49745:4:0;48915:853;;;;;;:::o;27664:922::-;27717:7;;-1:-1:-1;;;27795:15:0;;27791:102;;-1:-1:-1;;;27831:15:0;;;-1:-1:-1;27875:2:0;27865:12;27791:102;27920:6;27911:5;:15;27907:102;;27956:6;27947:15;;;-1:-1:-1;27991:2:0;27981:12;27907:102;28036:6;28027:5;:15;28023:102;;28072:6;28063:15;;;-1:-1:-1;28107:2:0;28097:12;28023:102;28152:5;28143;:14;28139:99;;28187:5;28178:14;;;-1:-1:-1;28221:1:0;28211:11;28139:99;28265:5;28256;:14;28252:99;;28300:5;28291:14;;;-1:-1:-1;28334:1:0;28324:11;28252:99;28378:5;28369;:14;28365:99;;28413:5;28404:14;;;-1:-1:-1;28447:1:0;28437:11;28365:99;28491:5;28482;:14;28478:66;;28527:1;28517:11;28572:6;27664:922;-1:-1:-1;;27664:922:0:o;4059:229::-;4196:12;4228:52;4250:6;4258:4;4264:1;4267:12;4196;5467;5481:23;5508:6;-1:-1:-1;;;;;5508:11:0;5527:5;5534:4;5508:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5466:73;;;;5557:69;5584:6;5592:7;5601:10;5613:12;5557:26;:69::i;:::-;5550:76;5179:455;-1:-1:-1;;;;;;;5179:455:0:o;7752:644::-;7937:12;7966:7;7962:427;;;7994:17;;7990:290;;-1:-1:-1;;;;;1597:19:0;;;8204:60;;;;-1:-1:-1;;;8204:60:0;;40849:2:1;8204:60:0;;;40831:21:1;40888:2;40868:18;;;40861:30;40927:31;40907:18;;;40900:59;40976:18;;8204:60:0;40647:353:1;8204:60:0;-1:-1:-1;8301:10:0;8294:17;;7962:427;8344:33;8352:10;8364:12;9099:17;;:21;9095:388;;9331:10;9325:17;9388:15;9375:10;9371:2;9367:19;9360:44;9095:388;9458:12;9451:20;;-1:-1:-1;;;9451:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;955:258::-;1027:1;1037:113;1051:6;1048:1;1045:13;1037:113;;;1127:11;;;1121:18;1108:11;;;1101:39;1073:2;1066:10;1037:113;;;1168:6;1165:1;1162:13;1159:48;;;-1:-1:-1;;1203:1:1;1185:16;;1178:27;955:258::o;1218:::-;1260:3;1298:5;1292:12;1325:6;1320:3;1313:19;1341:63;1397:6;1390:4;1385:3;1381:14;1374:4;1367:5;1363:16;1341:63;:::i;:::-;1458:2;1437:15;-1:-1:-1;;1433:29:1;1424:39;;;;1465:4;1420:50;;1218:258;-1:-1:-1;;1218:258:1:o;1481:220::-;1630:2;1619:9;1612:21;1593:4;1650:45;1691:2;1680:9;1676:18;1668:6;1650:45;:::i;1706:173::-;1774:20;;-1:-1:-1;;;;;1823:31:1;;1813:42;;1803:70;;1869:1;1866;1859:12;1803:70;1706:173;;;:::o;1884:186::-;1943:6;1996:2;1984:9;1975:7;1971:23;1967:32;1964:52;;;2012:1;2009;2002:12;1964:52;2035:29;2054:9;2035:29;:::i;2075:180::-;2134:6;2187:2;2175:9;2166:7;2162:23;2158:32;2155:52;;;2203:1;2200;2193:12;2155:52;-1:-1:-1;2226:23:1;;2075:180;-1:-1:-1;2075:180:1:o;2260:254::-;2328:6;2336;2389:2;2377:9;2368:7;2364:23;2360:32;2357:52;;;2405:1;2402;2395:12;2357:52;2428:29;2447:9;2428:29;:::i;:::-;2418:39;2504:2;2489:18;;;;2476:32;;-1:-1:-1;;;2260:254:1:o;2519:248::-;2587:6;2595;2648:2;2636:9;2627:7;2623:23;2619:32;2616:52;;;2664:1;2661;2654:12;2616:52;-1:-1:-1;;2687:23:1;;;2757:2;2742:18;;;2729:32;;-1:-1:-1;2519:248:1:o;2954:328::-;3031:6;3039;3047;3100:2;3088:9;3079:7;3075:23;3071:32;3068:52;;;3116:1;3113;3106:12;3068:52;3139:29;3158:9;3139:29;:::i;:::-;3129:39;;3187:38;3221:2;3210:9;3206:18;3187:38;:::i;:::-;3177:48;;3272:2;3261:9;3257:18;3244:32;3234:42;;2954:328;;;;;:::o;3287:316::-;3364:6;3372;3380;3433:2;3421:9;3412:7;3408:23;3404:32;3401:52;;;3449:1;3446;3439:12;3401:52;-1:-1:-1;;3472:23:1;;;3542:2;3527:18;;3514:32;;-1:-1:-1;3593:2:1;3578:18;;;3565:32;;3287:316;-1:-1:-1;3287:316:1:o;3608:118::-;3694:5;3687:13;3680:21;3673:5;3670:32;3660:60;;3716:1;3713;3706:12;3731:241;3787:6;3840:2;3828:9;3819:7;3815:23;3811:32;3808:52;;;3856:1;3853;3846:12;3808:52;3895:9;3882:23;3914:28;3936:5;3914:28;:::i;4617:315::-;4682:6;4690;4743:2;4731:9;4722:7;4718:23;4714:32;4711:52;;;4759:1;4756;4749:12;4711:52;4782:29;4801:9;4782:29;:::i;:::-;4772:39;;4861:2;4850:9;4846:18;4833:32;4874:28;4896:5;4874:28;:::i;:::-;4921:5;4911:15;;;4617:315;;;;;:::o;4937:127::-;4998:10;4993:3;4989:20;4986:1;4979:31;5029:4;5026:1;5019:15;5053:4;5050:1;5043:15;5069:632;5134:5;5164:18;5205:2;5197:6;5194:14;5191:40;;;5211:18;;:::i;:::-;5286:2;5280:9;5254:2;5340:15;;-1:-1:-1;;5336:24:1;;;5362:2;5332:33;5328:42;5316:55;;;5386:18;;;5406:22;;;5383:46;5380:72;;;5432:18;;:::i;:::-;5472:10;5468:2;5461:22;5501:6;5492:15;;5531:6;5523;5516:22;5571:3;5562:6;5557:3;5553:16;5550:25;5547:45;;;5588:1;5585;5578:12;5547:45;5638:6;5633:3;5626:4;5618:6;5614:17;5601:44;5693:1;5686:4;5677:6;5669;5665:19;5661:30;5654:41;;;;5069:632;;;;;:::o;5706:451::-;5775:6;5828:2;5816:9;5807:7;5803:23;5799:32;5796:52;;;5844:1;5841;5834:12;5796:52;5884:9;5871:23;5917:18;5909:6;5906:30;5903:50;;;5949:1;5946;5939:12;5903:50;5972:22;;6025:4;6017:13;;6013:27;-1:-1:-1;6003:55:1;;6054:1;6051;6044:12;6003:55;6077:74;6143:7;6138:2;6125:16;6120:2;6116;6112:11;6077:74;:::i;6162:667::-;6257:6;6265;6273;6281;6334:3;6322:9;6313:7;6309:23;6305:33;6302:53;;;6351:1;6348;6341:12;6302:53;6374:29;6393:9;6374:29;:::i;:::-;6364:39;;6422:38;6456:2;6445:9;6441:18;6422:38;:::i;:::-;6412:48;;6507:2;6496:9;6492:18;6479:32;6469:42;;6562:2;6551:9;6547:18;6534:32;6589:18;6581:6;6578:30;6575:50;;;6621:1;6618;6611:12;6575:50;6644:22;;6697:4;6689:13;;6685:27;-1:-1:-1;6675:55:1;;6726:1;6723;6716:12;6675:55;6749:74;6815:7;6810:2;6797:16;6792:2;6788;6784:11;6749:74;:::i;:::-;6739:84;;;6162:667;;;;;;;:::o;6834:592::-;6905:6;6913;6966:2;6954:9;6945:7;6941:23;6937:32;6934:52;;;6982:1;6979;6972:12;6934:52;7022:9;7009:23;7051:18;7092:2;7084:6;7081:14;7078:34;;;7108:1;7105;7098:12;7078:34;7146:6;7135:9;7131:22;7121:32;;7191:7;7184:4;7180:2;7176:13;7172:27;7162:55;;7213:1;7210;7203:12;7162:55;7253:2;7240:16;7279:2;7271:6;7268:14;7265:34;;;7295:1;7292;7285:12;7265:34;7340:7;7335:2;7326:6;7322:2;7318:15;7314:24;7311:37;7308:57;;;7361:1;7358;7351:12;7308:57;7392:2;7384:11;;;;;7414:6;;-1:-1:-1;6834:592:1;;-1:-1:-1;;;;6834:592:1:o;7431:260::-;7499:6;7507;7560:2;7548:9;7539:7;7535:23;7531:32;7528:52;;;7576:1;7573;7566:12;7528:52;7599:29;7618:9;7599:29;:::i;:::-;7589:39;;7647:38;7681:2;7670:9;7666:18;7647:38;:::i;:::-;7637:48;;7431:260;;;;;:::o;8056:127::-;8117:10;8112:3;8108:20;8105:1;8098:31;8148:4;8145:1;8138:15;8172:4;8169:1;8162:15;8188:168;8228:7;8294:1;8290;8286:6;8282:14;8279:1;8276:21;8271:1;8264:9;8257:17;8253:45;8250:71;;;8301:18;;:::i;:::-;-1:-1:-1;8341:9:1;;8188:168::o;8493:217::-;8533:1;8559;8549:132;;8603:10;8598:3;8594:20;8591:1;8584:31;8638:4;8635:1;8628:15;8666:4;8663:1;8656:15;8549:132;-1:-1:-1;8695:9:1;;8493:217::o;8715:125::-;8755:4;8783:1;8780;8777:8;8774:34;;;8788:18;;:::i;:::-;-1:-1:-1;8825:9:1;;8715:125::o;9124:245::-;9191:6;9244:2;9232:9;9223:7;9219:23;9215:32;9212:52;;;9260:1;9257;9250:12;9212:52;9292:9;9286:16;9311:28;9333:5;9311:28;:::i;9374:380::-;9453:1;9449:12;;;;9496;;;9517:61;;9571:4;9563:6;9559:17;9549:27;;9517:61;9624:2;9616:6;9613:14;9593:18;9590:38;9587:161;;;9670:10;9665:3;9661:20;9658:1;9651:31;9705:4;9702:1;9695:15;9733:4;9730:1;9723:15;10997:128;11037:3;11068:1;11064:6;11061:1;11058:13;11055:39;;;11074:18;;:::i;:::-;-1:-1:-1;11110:9:1;;10997:128::o;11738:422::-;11827:1;11870:5;11827:1;11884:270;11905:7;11895:8;11892:21;11884:270;;;11964:4;11960:1;11956:6;11952:17;11946:4;11943:27;11940:53;;;11973:18;;:::i;:::-;12023:7;12013:8;12009:22;12006:55;;;12043:16;;;;12006:55;12122:22;;;;12082:15;;;;11884:270;;;11888:3;11738:422;;;;;:::o;12165:806::-;12214:5;12244:8;12234:80;;-1:-1:-1;12285:1:1;12299:5;;12234:80;12333:4;12323:76;;-1:-1:-1;12370:1:1;12384:5;;12323:76;12415:4;12433:1;12428:59;;;;12501:1;12496:130;;;;12408:218;;12428:59;12458:1;12449:10;;12472:5;;;12496:130;12533:3;12523:8;12520:17;12517:43;;;12540:18;;:::i;:::-;-1:-1:-1;;12596:1:1;12582:16;;12611:5;;12408:218;;12710:2;12700:8;12697:16;12691:3;12685:4;12682:13;12678:36;12672:2;12662:8;12659:16;12654:2;12648:4;12645:12;12641:35;12638:77;12635:159;;;-1:-1:-1;12747:19:1;;;12779:5;;12635:159;12826:34;12851:8;12845:4;12826:34;:::i;:::-;12896:6;12892:1;12888:6;12884:19;12875:7;12872:32;12869:58;;;12907:18;;:::i;:::-;12945:20;;12165:806;-1:-1:-1;;;12165:806:1:o;12976:131::-;13036:5;13065:36;13092:8;13086:4;13065:36;:::i;13112:409::-;13314:2;13296:21;;;13353:2;13333:18;;;13326:30;13392:34;13387:2;13372:18;;13365:62;-1:-1:-1;;;13458:2:1;13443:18;;13436:43;13511:3;13496:19;;13112:409::o;13938:354::-;14140:2;14122:21;;;14179:2;14159:18;;;14152:30;14218:32;14213:2;14198:18;;14191:60;14283:2;14268:18;;13938:354::o;14297:343::-;14499:2;14481:21;;;14538:2;14518:18;;;14511:30;-1:-1:-1;;;14572:2:1;14557:18;;14550:49;14631:2;14616:18;;14297:343::o;14645:344::-;14847:2;14829:21;;;14886:2;14866:18;;;14859:30;-1:-1:-1;;;14920:2:1;14905:18;;14898:50;14980:2;14965:18;;14645:344::o;14994:339::-;15196:2;15178:21;;;15235:2;15215:18;;;15208:30;-1:-1:-1;;;15269:2:1;15254:18;;15247:45;15324:2;15309:18;;14994:339::o;15338:184::-;15408:6;15461:2;15449:9;15440:7;15436:23;15432:32;15429:52;;;15477:1;15474;15467:12;15429:52;-1:-1:-1;15500:16:1;;15338:184;-1:-1:-1;15338:184:1:o;16285:397::-;16487:2;16469:21;;;16526:2;16506:18;;;16499:30;16565:34;16560:2;16545:18;;16538:62;-1:-1:-1;;;16631:2:1;16616:18;;16609:31;16672:3;16657:19;;16285:397::o;19296:127::-;19357:10;19352:3;19348:20;19345:1;19338:31;19388:4;19385:1;19378:15;19412:4;19409:1;19402:15;23022:349;23224:2;23206:21;;;23263:2;23243:18;;;23236:30;23302:27;23297:2;23282:18;;23275:55;23362:2;23347:18;;23022:349::o;31121:470::-;31300:3;31338:6;31332:13;31354:53;31400:6;31395:3;31388:4;31380:6;31376:17;31354:53;:::i;:::-;31470:13;;31429:16;;;;31492:57;31470:13;31429:16;31526:4;31514:17;;31492:57;:::i;:::-;31565:20;;31121:470;-1:-1:-1;;;;31121:470:1:o;32481:1186::-;32590:4;32619:2;32648;32637:9;32630:21;32671:1;32704:6;32698:13;32734:3;32756:1;32784:9;32780:2;32776:18;32766:28;;32844:2;32833:9;32829:18;32866;32856:61;;32910:4;32902:6;32898:17;32888:27;;32856:61;32963:2;32955:6;32952:14;32932:18;32929:38;32926:165;;;-1:-1:-1;;;32990:33:1;;33046:4;33043:1;33036:15;33076:4;32997:3;33064:17;32926:165;33147:18;;;887:19;;;939:4;930:14;33190:18;33217:100;;;;33331:1;33326:315;;;;33183:458;;33217:100;-1:-1:-1;;33250:24:1;;33238:37;;33295:12;;;;-1:-1:-1;33217:100:1;;33326:315;32428:1;32421:14;;;32465:4;32452:18;;33421:1;33435:165;33449:6;33446:1;33443:13;33435:165;;;33527:14;;33514:11;;;33507:35;33570:16;;;;33464:10;;33435:165;;;33620:11;;;-1:-1:-1;;33183:458:1;-1:-1:-1;33658:3:1;;32481:1186;-1:-1:-1;;;;;;;;;32481:1186:1:o;35988:401::-;36190:2;36172:21;;;36229:2;36209:18;;;36202:30;36268:34;36263:2;36248:18;;36241:62;-1:-1:-1;;;36334:2:1;36319:18;;36312:35;36379:3;36364:19;;35988:401::o;38251:414::-;38453:2;38435:21;;;38492:2;38472:18;;;38465:30;38531:34;38526:2;38511:18;;38504:62;-1:-1:-1;;;38597:2:1;38582:18;;38575:48;38655:3;38640:19;;38251:414::o;38670:127::-;38731:10;38726:3;38722:20;38719:1;38712:31;38762:4;38759:1;38752:15;38786:4;38783:1;38776:15;39213:489;-1:-1:-1;;;;;39482:15:1;;;39464:34;;39534:15;;39529:2;39514:18;;39507:43;39581:2;39566:18;;39559:34;;;39629:3;39624:2;39609:18;;39602:31;;;39407:4;;39650:46;;39676:19;;39668:6;39650:46;:::i;39707:249::-;39776:6;39829:2;39817:9;39808:7;39804:23;39800:32;39797:52;;;39845:1;39842;39835:12;39797:52;39877:9;39871:16;39896:30;39920:5;39896:30;:::i;40368:274::-;40497:3;40535:6;40529:13;40551:53;40597:6;40592:3;40585:4;40577:6;40573:17;40551:53;:::i;:::-;40620:16;;;;;40368:274;-1:-1:-1;;40368:274:1:o

Swarm Source

ipfs://29cb81d5165be54f4036811dd4e81e0d784d1562404c96ca7d292941953b652b
Loading