Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
VeSixUpgradeable
Compiler Version
v0.8.27+commit.40a35a09
Contract Source Code (Solidity)
/** *Submitted for verification at SonicScan.org on 2025-03-29 */ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * 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[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } pragma solidity ^0.8.20; /** * @dev Required interface of an ERC-721 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 ERC-721 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 ERC-721 * 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 address zero. * * 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); } pragma solidity ^0.8.20; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); } pragma solidity ^0.8.20; /** * @title ERC-721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC-721 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); } pragma solidity ^0.8.20; /** * @dev Standard ERC-20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC-721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC-1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); } pragma solidity ^0.8.20; /** * @dev Library that provide common ERC-721 utility functions. * * See https://eips.ethereum.org/EIPS/eip-721[ERC-721]. * * _Available since v5.1._ */ library ERC721Utils { /** * @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received} * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). * * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). * Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept * the transfer. */ function checkOnERC721Received( address operator, address from, address to, uint256 tokenId, bytes memory data ) internal { if (to.code.length > 0) { try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) { if (retval != IERC721Receiver.onERC721Received.selector) { // Token rejected revert IERC721Errors.ERC721InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-IERC721Receiver implementer revert IERC721Errors.ERC721InvalidReceiver(to); } else { assembly ("memory-safe") { revert(add(32, reason), mload(reason)) } } } } } } pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } } pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } pragma solidity ^0.8.20; /** * @dev Helper library for emitting standardized panic codes. * * ```solidity * contract Example { * using Panic for uint256; * * // Use any of the declared internal constants * function foo() { Panic.GENERIC.panic(); } * * // Alternatively * function foo() { Panic.panic(Panic.GENERIC); } * } * ``` * * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. * * _Available since v5.1._ */ // slither-disable-next-line unused-state library Panic { /// @dev generic / unspecified error uint256 internal constant GENERIC = 0x00; /// @dev used by the assert() builtin uint256 internal constant ASSERT = 0x01; /// @dev arithmetic underflow or overflow uint256 internal constant UNDER_OVERFLOW = 0x11; /// @dev division or modulo by zero uint256 internal constant DIVISION_BY_ZERO = 0x12; /// @dev enum conversion error uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; /// @dev invalid encoding in storage uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; /// @dev empty array pop uint256 internal constant EMPTY_ARRAY_POP = 0x31; /// @dev array out of bounds access uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; /// @dev resource error (too large allocation or too large array) uint256 internal constant RESOURCE_ERROR = 0x41; /// @dev calling invalid internal function uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; /// @dev Reverts with a panic code. Recommended to use with /// the internal constants with predefined codes. function panic(uint256 code) internal pure { assembly ("memory-safe") { mstore(0x00, 0x4e487b71) mstore(0x20, code) revert(0x1c, 0x24) } } } // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } } pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an success flag (no overflow). */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow). */ function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow). */ function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a success flag (no division by zero). */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). */ function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * SafeCast.toUint(condition)); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(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 towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. Panic.panic(Panic.DIVISION_BY_ZERO); } // The following calculation ensures accurate ceiling division without overflow. // Since a is non-zero, (a - 1) / b will not overflow. // The largest possible result occurs when (a - 1) / b is type(uint256).max, // but the largest value we can obtain is type(uint256).max - 1, which happens // when a = type(uint256).max and b = 1. unchecked { return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); } } /** * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * * 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²⁵⁶ and mod 2²⁵⁶ - 1, then use // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2²⁵⁶ + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0. if (denominator <= prod1) { Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW)); } /////////////////////////////////////////////// // 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. uint256 twos = denominator & (0 - denominator); 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²⁵⁶ / 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²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv ≡ 1 mod 2⁴. 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⁸ inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ inverse *= 2 - denominator * inverse; // inverse mod 2³² inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ // 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²⁵⁶. Since the preconditions guarantee that the outcome is // less than 2²⁵⁶, 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; } } /** * @dev 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) { return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } /** * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. * * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0. * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. * * If the input value is not inversible, 0 is returned. * * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}. */ function invMod(uint256 a, uint256 n) internal pure returns (uint256) { unchecked { if (n == 0) return 0; // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) // Used to compute integers x and y such that: ax + ny = gcd(a, n). // When the gcd is 1, then the inverse of a modulo n exists and it's x. // ax + ny = 1 // ax = 1 + (-y)n // ax ≡ 1 (mod n) # x is the inverse of a modulo n // If the remainder is 0 the gcd is n right away. uint256 remainder = a % n; uint256 gcd = n; // Therefore the initial coefficients are: // ax + ny = gcd(a, n) = n // 0a + 1n = n int256 x = 0; int256 y = 1; while (remainder != 0) { uint256 quotient = gcd / remainder; (gcd, remainder) = ( // The old remainder is the next gcd to try. remainder, // Compute the next remainder. // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd // where gcd is at most n (capped to type(uint256).max) gcd - remainder * quotient ); (x, y) = ( // Increment the coefficient of a. y, // Decrement the coefficient of n. // Can overflow, but the result is casted to uint256 so that the // next value of y is "wrapped around" to a value between 0 and n - 1. x - y * int256(quotient) ); } if (gcd != 1) return 0; // No inverse exists. return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. } } /** * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`. * * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that * `a**(p-2)` is the modular multiplicative inverse of a in Fp. * * NOTE: this function does NOT check that `p` is a prime greater than `2`. */ function invModPrime(uint256 a, uint256 p) internal view returns (uint256) { unchecked { return Math.modExp(a, p - 2, p); } } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) * * Requirements: * - modulus can't be zero * - underlying staticcall to precompile must succeed * * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make * sure the chain you're using it on supports the precompiled contract for modular exponentiation * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, * the underlying function will succeed given the lack of a revert, but the result may be incorrectly * interpreted as 0. */ function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) { (bool success, uint256 result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying * to operate modulo 0 or if the underlying precompile reverted. * * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack * of a revert, but the result may be incorrectly interpreted as 0. */ function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) { if (m == 0) return (false, 0); assembly ("memory-safe") { let ptr := mload(0x40) // | Offset | Content | Content (Hex) | // |-----------|------------|--------------------------------------------------------------------| // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x60:0x7f | value of b | 0x<.............................................................b> | // | 0x80:0x9f | value of e | 0x<.............................................................e> | // | 0xa0:0xbf | value of m | 0x<.............................................................m> | mstore(ptr, 0x20) mstore(add(ptr, 0x20), 0x20) mstore(add(ptr, 0x40), 0x20) mstore(add(ptr, 0x60), b) mstore(add(ptr, 0x80), e) mstore(add(ptr, 0xa0), m) // Given the result < m, it's guaranteed to fit in 32 bytes, // so we can use the memory scratch space located at offset 0. success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) result := mload(0x00) } } /** * @dev Variant of {modExp} that supports inputs of arbitrary length. */ function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) { (bool success, bytes memory result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Variant of {tryModExp} that supports inputs of arbitrary length. */ function tryModExp( bytes memory b, bytes memory e, bytes memory m ) internal view returns (bool success, bytes memory result) { if (_zeroBytes(m)) return (false, new bytes(0)); uint256 mLen = m.length; // Encode call args in result and move the free memory pointer result = abi.encodePacked(b.length, e.length, mLen, b, e, m); assembly ("memory-safe") { let dataPtr := add(result, 0x20) // Write result on top of args to avoid allocating extra memory. success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen) // Overwrite the length. // result.length > returndatasize() is guaranteed because returndatasize() == m.length mstore(result, mLen) // Set the memory pointer after the returned data. mstore(0x40, add(dataPtr, mLen)) } } /** * @dev Returns whether the provided byte array is zero. */ function _zeroBytes(bytes memory byteArray) private pure returns (bool) { for (uint256 i = 0; i < byteArray.length; ++i) { if (byteArray[i] != 0) { return false; } } return true; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * This method is based on Newton's method for computing square roots; the algorithm is restricted to only * using integer operations. */ function sqrt(uint256 a) internal pure returns (uint256) { unchecked { // Take care of easy edge cases when a == 0 or a == 1 if (a <= 1) { return a; } // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between // the current value as `ε_n = | x_n - sqrt(a) |`. // // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is // bigger than any uint256. // // By noticing that // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar // to the msb function. uint256 aa = a; uint256 xn = 1; if (aa >= (1 << 128)) { aa >>= 128; xn <<= 64; } if (aa >= (1 << 64)) { aa >>= 64; xn <<= 32; } if (aa >= (1 << 32)) { aa >>= 32; xn <<= 16; } if (aa >= (1 << 16)) { aa >>= 16; xn <<= 8; } if (aa >= (1 << 8)) { aa >>= 8; xn <<= 4; } if (aa >= (1 << 4)) { aa >>= 4; xn <<= 2; } if (aa >= (1 << 2)) { xn <<= 1; } // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1). // // We can refine our estimation by noticing that the middle of that interval minimizes the error. // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). // This is going to be our x_0 (and ε_0) xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) // From here, Newton's method give us: // x_{n+1} = (x_n + a / x_n) / 2 // // One should note that: // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a // = ((x_n² + a) / (2 * x_n))² - a // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) // = (x_n² - a)² / (2 * x_n)² // = ((x_n² - a) / (2 * x_n))² // ≥ 0 // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n // // This gives us the proof of quadratic convergence of the sequence: // ε_{n+1} = | x_{n+1} - sqrt(a) | // = | (x_n + a / x_n) / 2 - sqrt(a) | // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | // = | (x_n - sqrt(a))² / (2 * x_n) | // = | ε_n² / (2 * x_n) | // = ε_n² / | (2 * x_n) | // // For the first iteration, we have a special case where x_0 is known: // ε_1 = ε_0² / | (2 * x_0) | // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) // ≤ 2**(2*e-4) / (3 * 2**(e-1)) // ≤ 2**(e-3) / 3 // ≤ 2**(e-3-log2(3)) // ≤ 2**(e-4.5) // // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: // ε_{n+1} = ε_n² / | (2 * x_n) | // ≤ (2**(e-k))² / (2 * 2**(e-1)) // ≤ 2**(2*e-2*k) / 2**e // ≤ 2**(e-2*k) xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either // sqrt(a) or sqrt(a) + 1. return xn - SafeCast.toUint(xn > a / xn); } } /** * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 exp; unchecked { exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); value >>= exp; result += exp; exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); value >>= exp; result += exp; exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); value >>= exp; result += exp; exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); value >>= exp; result += exp; exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); value >>= exp; result += exp; exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); value >>= exp; result += exp; exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); value >>= exp; result += exp; result += SafeCast.toUint(value > 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * 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; uint256 isGt; unchecked { isGt = SafeCast.toUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; isGt = SafeCast.toUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; isGt = SafeCast.toUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; isGt = SafeCast.toUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; result += SafeCast.toUint(value > (1 << 8) - 1); } return result; } /** * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } } pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * int256(SafeCast.toUint(condition))); } } /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return ternary(a < b, a, b); } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson. // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift, // taking advantage of the most significant (or "sign" bit) in two's complement representation. // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result, // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative). int256 mask = n >> 255; // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it. return uint256((n + mask) ^ mask); } } } pragma solidity ^0.8.20; /** * @dev String operations. */ library Strings { using SafeCast for *; bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev The string being parsed contains characters that are not in scope of the given base. */ error StringsInvalidChar(); /** * @dev The string being parsed is not a properly formatted address. */ error StringsInvalidAddressFormat(); /** * @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; assembly ("memory-safe") { ptr := add(buffer, add(32, length)) } while (true) { ptr--; assembly ("memory-safe") { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @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) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } 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); } /** * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal * representation, according to EIP-55. */ function toChecksumHexString(address addr) internal pure returns (string memory) { bytes memory buffer = bytes(toHexString(addr)); // hash the hex part of buffer (skip length + 2 bytes, length 40) uint256 hashValue; assembly ("memory-safe") { hashValue := shr(96, keccak256(add(buffer, 0x22), 40)) } for (uint256 i = 41; i > 1; --i) { // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f) if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) { // case shift by xoring with 0x20 buffer[i] ^= 0x20; } hashValue >>= 4; } return string(buffer); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } /** * @dev Parse a decimal string and returns the value as a `uint256`. * * Requirements: * - The string must be formatted as `[0-9]*` * - The result must fit into an `uint256` type */ function parseUint(string memory input) internal pure returns (uint256) { return parseUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `[0-9]*` * - The result must fit into an `uint256` type */ function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { (bool success, uint256 value) = tryParseUint(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) { return _tryParseUintUncheckedBounds(input, 0, bytes(input).length); } /** * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid * character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseUint( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, uint256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseUintUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseUintUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, uint256 value) { bytes memory buffer = bytes(input); uint256 result = 0; for (uint256 i = begin; i < end; ++i) { uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); if (chr > 9) return (false, 0); result *= 10; result += chr; } return (true, result); } /** * @dev Parse a decimal string and returns the value as a `int256`. * * Requirements: * - The string must be formatted as `[-+]?[0-9]*` * - The result must fit in an `int256` type. */ function parseInt(string memory input) internal pure returns (int256) { return parseInt(input, 0, bytes(input).length); } /** * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `[-+]?[0-9]*` * - The result must fit in an `int256` type. */ function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) { (bool success, int256 value) = tryParseInt(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if * the result does not fit in a `int256`. * * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. */ function tryParseInt(string memory input) internal pure returns (bool success, int256 value) { return _tryParseIntUncheckedBounds(input, 0, bytes(input).length); } uint256 private constant ABS_MIN_INT256 = 2 ** 255; /** * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid * character or if the result does not fit in a `int256`. * * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. */ function tryParseInt( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, int256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseIntUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseIntUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, int256 value) { bytes memory buffer = bytes(input); // Check presence of a negative sign. bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty bool positiveSign = sign == bytes1("+"); bool negativeSign = sign == bytes1("-"); uint256 offset = (positiveSign || negativeSign).toUint(); (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end); if (absSuccess && absValue < ABS_MIN_INT256) { return (true, negativeSign ? -int256(absValue) : int256(absValue)); } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) { return (true, type(int256).min); } else return (false, 0); } /** * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`. * * Requirements: * - The string must be formatted as `(0x)?[0-9a-fA-F]*` * - The result must fit in an `uint256` type. */ function parseHexUint(string memory input) internal pure returns (uint256) { return parseHexUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `(0x)?[0-9a-fA-F]*` * - The result must fit in an `uint256` type. */ function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { (bool success, uint256 value) = tryParseHexUint(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) { return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length); } /** * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an * invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseHexUint( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, uint256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseHexUintUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseHexUintUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, uint256 value) { bytes memory buffer = bytes(input); // skip 0x prefix if present bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty uint256 offset = hasPrefix.toUint() * 2; uint256 result = 0; for (uint256 i = begin + offset; i < end; ++i) { uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); if (chr > 15) return (false, 0); result *= 16; unchecked { // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check). // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked. result += chr; } } return (true, result); } /** * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`. * * Requirements: * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}` */ function parseAddress(string memory input) internal pure returns (address) { return parseAddress(input, 0, bytes(input).length); } /** * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}` */ function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) { (bool success, address value) = tryParseAddress(input, begin, end); if (!success) revert StringsInvalidAddressFormat(); return value; } /** * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly * formatted address. See {parseAddress} requirements. */ function tryParseAddress(string memory input) internal pure returns (bool success, address value) { return tryParseAddress(input, 0, bytes(input).length); } /** * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly * formatted address. See {parseAddress} requirements. */ function tryParseAddress( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, address value) { if (end > bytes(input).length || begin > end) return (false, address(0)); bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty uint256 expectedLength = 40 + hasPrefix.toUint() * 2; // check that input is the correct length if (end - begin == expectedLength) { // length guarantees that this does not overflow, and value is at most type(uint160).max (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end); return (s, address(uint160(v))); } else { return (false, address(0)); } } function _tryParseChr(bytes1 chr) private pure returns (uint8) { uint8 value = uint8(chr); // Try to parse `chr`: // - Case 1: [0-9] // - Case 2: [a-f] // - Case 3: [A-F] // - otherwise not supported unchecked { if (value > 47 && value < 58) value -= 48; else if (value > 96 && value < 103) value -= 87; else if (value > 64 && value < 71) value -= 55; else return type(uint8).max; } return value; } /** * @dev Reads a bytes32 from a bytes array without bounds checking. * * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the * assembly block as such would prevent some optimizations. */ function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) { // This is not memory safe in the general case, but all calls to this private function are within bounds. assembly ("memory-safe") { value := mload(add(buffer, add(0x20, offset))) } } } pragma solidity ^0.8.20; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 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); * } * ``` */ abstract contract ERC165Upgradeable is Initializable, IERC165 { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } } pragma solidity ^0.8.20; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ abstract contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721, IERC721Metadata, IERC721Errors { using Strings for uint256; /// @custom:storage-location erc7201:openzeppelin.storage.ERC721 struct ERC721Storage { // Token name string _name; // Token symbol string _symbol; mapping(uint256 tokenId => address) _owners; mapping(address owner => uint256) _balances; mapping(uint256 tokenId => address) _tokenApprovals; mapping(address owner => mapping(address operator => bool)) _operatorApprovals; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC721")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ERC721StorageLocation = 0x80bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab0079300; function _getERC721Storage() private pure returns (ERC721Storage storage $) { assembly { $.slot := ERC721StorageLocation } } /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC721_init_unchained(name_, symbol_); } function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { ERC721Storage storage $ = _getERC721Storage(); $._name = name_; $._symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, 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 returns (uint256) { ERC721Storage storage $ = _getERC721Storage(); if (owner == address(0)) { revert ERC721InvalidOwner(address(0)); } return $._balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual returns (address) { return _requireOwned(tokenId); } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual returns (string memory) { ERC721Storage storage $ = _getERC721Storage(); return $._name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual returns (string memory) { ERC721Storage storage $ = _getERC721Storage(); return $._symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual returns (string memory) { _requireOwned(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string.concat(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 { _approve(to, tokenId, _msgSender()); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual returns (address) { _requireOwned(tokenId); return _getApproved(tokenId); } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual returns (bool) { ERC721Storage storage $ = _getERC721Storage(); return $._operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here. address previousOwner = _update(to, tokenId, _msgSender()); if (previousOwner != from) { revert ERC721IncorrectOwner(from, tokenId, previousOwner); } } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual { transferFrom(from, to, tokenId); ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist * * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the * core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`. */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { ERC721Storage storage $ = _getERC721Storage(); return $._owners[tokenId]; } /** * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted. */ function _getApproved(uint256 tokenId) internal view virtual returns (address) { ERC721Storage storage $ = _getERC721Storage(); return $._tokenApprovals[tokenId]; } /** * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in * particular (ignoring whether it is owned by `owner`). * * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this * assumption. */ function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) { return spender != address(0) && (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender); } /** * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner. * Reverts if: * - `spender` does not have approval from `owner` for `tokenId`. * - `spender` does not have approval to manage all of `owner`'s assets. * * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this * assumption. */ function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual { if (!_isAuthorized(owner, spender, tokenId)) { if (owner == address(0)) { revert ERC721NonexistentToken(tokenId); } else { revert ERC721InsufficientApproval(spender, tokenId); } } } /** * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. * * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that * a uint256 would ever overflow from increments when these increments are bounded to uint128 values. * * WARNING: Increasing an account's balance using this function tends to be paired with an override of the * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership * remain consistent with one another. */ function _increaseBalance(address account, uint128 value) internal virtual { ERC721Storage storage $ = _getERC721Storage(); unchecked { $._balances[account] += value; } } /** * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update. * * The `auth` argument is optional. If the value passed is non 0, then this function will check that * `auth` is either the owner of the token, or approved to operate on the token (by the owner). * * Emits a {Transfer} event. * * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}. */ function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) { ERC721Storage storage $ = _getERC721Storage(); address from = _ownerOf(tokenId); // Perform (optional) operator check if (auth != address(0)) { _checkAuthorized(from, auth, tokenId); } // Execute the update if (from != address(0)) { // Clear approval. No need to re-authorize or emit the Approval event _approve(address(0), tokenId, address(0), false); unchecked { $._balances[from] -= 1; } } if (to != address(0)) { unchecked { $._balances[to] += 1; } } $._owners[tokenId] = to; emit Transfer(from, to, tokenId); return from; } /** * @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 { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } address previousOwner = _update(to, tokenId, address(0)); if (previousOwner != address(0)) { revert ERC721InvalidSender(address(0)); } } /** * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance. * * 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 { _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); ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data); } /** * @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 { address previousOwner = _update(address(0), tokenId, address(0)); if (previousOwner == address(0)) { revert ERC721NonexistentToken(tokenId); } } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } address previousOwner = _update(to, tokenId, address(0)); if (previousOwner == address(0)) { revert ERC721NonexistentToken(tokenId); } else if (previousOwner != from) { revert ERC721IncorrectOwner(from, tokenId, previousOwner); } } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients * are aware of the ERC-721 standard 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 like {safeTransferFrom} in the sense that it invokes * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `tokenId` token must exist and be owned by `from`. * - `to` cannot be the zero address. * - `from` cannot be the zero address. * - 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) internal { _safeTransfer(from, to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data); } /** * @dev Approve `to` to operate on `tokenId` * * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is * either the owner of the token, or approved to operate on all tokens held by this owner. * * Emits an {Approval} event. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address to, uint256 tokenId, address auth) internal { _approve(to, tokenId, auth, true); } /** * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not * emitted in the context of transfers. */ function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual { ERC721Storage storage $ = _getERC721Storage(); // Avoid reading the owner unless necessary if (emitEvent || auth != address(0)) { address owner = _requireOwned(tokenId); // We do not use _isAuthorized because single-token approvals should not be able to call approve if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) { revert ERC721InvalidApprover(auth); } if (emitEvent) { emit Approval(owner, to, tokenId); } } $._tokenApprovals[tokenId] = to; } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Requirements: * - operator can't be the address zero. * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { ERC721Storage storage $ = _getERC721Storage(); if (operator == address(0)) { revert ERC721InvalidOperator(operator); } $._operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned). * Returns the owner. * * Overrides to ownership logic should be done to {_ownerOf}. */ function _requireOwned(uint256 tokenId) internal view returns (address) { address owner = _ownerOf(tokenId); if (owner == address(0)) { revert ERC721NonexistentToken(tokenId); } return owner; } } pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @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); } 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. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20PermitUpgradeable { /** * @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]. * * CAUTION: See Security Considerations above. */ 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); } pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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); } } } 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 SafeERC20Upgradeable { using AddressUpgradeable for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20Upgradeable 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(IERC20Upgradeable 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)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20PermitUpgradeable 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(IERC20Upgradeable 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"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation 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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token)); } } pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _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; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; } pragma solidity ^0.8.0; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; } pragma solidity ^0.8.20; /** * @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. * * The initial owner is set to the address provided by the deployer. 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 OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @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) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } pragma solidity 0.8.27; interface IRewardsDistributor { function earned(uint256 tokenId, address rewardToken) external view returns (uint256); function getClaimableRewards(uint256 tokenId) external view returns ( address[] memory tokens, uint256[] memory amounts, uint256[] memory periods ); function queueNewRewards(address rewardToken, uint256 amount) external; function notifyRewardAmount(address rewardToken, uint256 amount) external; function getRewardTokens() external view returns (address[] memory); function lastTimeRewardApplicable(address rewardToken) external view returns (uint256); function claim(uint256 tokenId) external; } //@author 0xPhant0m based on Andre Cronje's voteEscrow contract for Solidly pragma solidity 0.8.27; contract VeSixUpgradeable is ERC721Upgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable, OwnableUpgradeable { using SafeERC20Upgradeable for IERC20Upgradeable; // Custom errors error InvalidAmount(); error InvalidDuration(); error TransferFailed(); error NotTokenOwner(); error LockNotExpired(); error ZeroReward(); error InvalidToken(); error InvalidArtProxy(); error ZeroAddress(); error DeadlineExpired(); error LockExpired(); error ExceedsMaxLocks(); error InvalidRewardRate(); error SlippageExceeded(); error MaxRewardRateExceeded(); error TokenNotExists(); error LockNotExists(); error MultiplierTooHigh(); error InvalidMultiplier(); error ArithmeticError(); struct Point { int128 bias; // Current farming power int128 slope; // Farming power decrease rate uint32 ts; // Timestamp of point uint32 blk; // Block number } struct LockedBalance { int128 amount; uint32 end; } struct LockPosition { uint128 amount; uint128 slope; uint32 endTime; uint32 lastUpdate; } // Constants uint32 private constant MAXTIME = 180 days; uint32 private constant WEEK = 7 * 86400; uint128 private constant MAX_MULTIPLIER = 4e18; uint128 private constant BASE_MULTIPLIER = 1e18; uint128 private constant PRECISION = 1e18; uint8 private constant MAX_LOCKS_PER_USER = 100; uint128 private constant MAX_REWARD_RATE = 1000e18; int128 private constant iMAXTIME = int128(uint128(MAXTIME)); // State variables IERC20Upgradeable private _lockedToken; IRewardsDistributor private _distributor; uint32 private _nextTokenId; mapping(uint256 => LockPosition) public _locks; mapping(address => uint8) public _userLockCount; // Point history state mapping(uint32 => Point) public pointHistory; uint32 public epoch; mapping(uint256 => uint32) public userPointEpoch; mapping(uint256 => mapping(uint32 => Point)) public userPointHistory; mapping(uint32 => int128) public slopeChanges; address public artProxy; uint32 MAX_BLOCK_DRIFT = 15; uint128 private _totalWeightedSupply; // Emergency recovery address private _emergencyRecoveryAddress; bool private _emergencyMode; // Events event Deposit( address indexed user, uint256 indexed tokenId, uint128 amount, uint32 lockTime ); event Withdraw( address indexed user, uint256 indexed tokenId, uint128 amount ); event RewardClaimed( address indexed user, uint256 indexed tokenId, uint128 reward ); event EmergencyModeEnabled(address recoveryAddress); event EmergencyWithdraw( address indexed user, uint256 indexed tokenId, uint128 amount ); event LockExtended( address indexed user, uint256 indexed tokenId, uint32 newEndTime, uint128 newMultiplier ); event AmountIncreased( address indexed user, uint256 indexed tokenId, uint128 additionalAmount, uint128 newTotalAmount, uint128 newMultiplier ); // Storage gap for future upgrades uint256[49] private __gap; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize( address lockedToken_, address emergencyRecovery, string memory name, string memory symbol ) public initializer { if (lockedToken_ == address(0) || emergencyRecovery == address(0)) revert ZeroAddress(); __ERC721_init(name, symbol); __ReentrancyGuard_init(); __Pausable_init(); __Ownable_init(msg.sender); _pause(); _lockedToken = IERC20Upgradeable(lockedToken_); _emergencyRecoveryAddress = emergencyRecovery; // Initialize point history pointHistory[0].blk = uint32(block.number); pointHistory[0].ts = uint32(block.timestamp); } function setDistributor(address distributor_) external onlyOwner { if (distributor_ == address(0)) revert ZeroAddress(); if (address(_distributor) != address(0)) revert("Distributor already set"); _distributor = IRewardsDistributor(distributor_); } // Modifiers modifier validDeadline(uint256 deadline) { if (block.timestamp > deadline) revert DeadlineExpired(); _; } modifier poke(uint256 tokenId) { LockPosition memory lock = _locks[tokenId]; if (lock.amount > 0 && uint32(block.timestamp) < lock.endTime) { // Calculate time-based parameters based on the corrected calculation uint32 timeLeft = lock.endTime - uint32(block.timestamp); // Get the current multiplier from the corrected algorithm uint256 timeRatio = (uint256(timeLeft) * PRECISION) / MAXTIME; uint256 multiplierCalc = BASE_MULTIPLIER + (uint256(MAX_MULTIPLIER - BASE_MULTIPLIER) * timeRatio) / PRECISION; uint128 newMultiplier = uint128(multiplierCalc); if (newMultiplier > MAX_MULTIPLIER) newMultiplier = MAX_MULTIPLIER; if (newMultiplier < BASE_MULTIPLIER) newMultiplier = BASE_MULTIPLIER; // Calculate proper slope based on the corrected calculation uint256 slopeCalc = (uint256(lock.amount) / MAXTIME) * PRECISION; uint128 newSlope = uint128(slopeCalc); // Only update if slope is different or it's been a while since last update if (lock.slope != newSlope || (block.timestamp - lock.lastUpdate) > 1 days) { // Record previous weighted supply value uint128 oldMultiplier; if (lock.slope > 0) { uint256 oldTimeRatio = (uint256(timeLeft) * PRECISION) / MAXTIME; uint256 oldMultiplierCalc = BASE_MULTIPLIER + (uint256(MAX_MULTIPLIER - BASE_MULTIPLIER) * oldTimeRatio) / PRECISION; oldMultiplier = uint128(oldMultiplierCalc); if (oldMultiplier > MAX_MULTIPLIER) oldMultiplier = MAX_MULTIPLIER; if (oldMultiplier < BASE_MULTIPLIER) oldMultiplier = BASE_MULTIPLIER; } else { oldMultiplier = BASE_MULTIPLIER; } uint256 oldWeightedAmount = (uint256(lock.amount) * oldMultiplier) / PRECISION; uint256 newWeightedAmount = (uint256(lock.amount) * newMultiplier) / PRECISION; // Update weighted supply by the difference if (newWeightedAmount > oldWeightedAmount) { uint256 increase = newWeightedAmount - oldWeightedAmount; _totalWeightedSupply += uint128(increase); } else if (oldWeightedAmount > newWeightedAmount) { uint256 decrease = oldWeightedAmount - newWeightedAmount; if (decrease > _totalWeightedSupply) { _totalWeightedSupply = 0; // Safeguard against underflow } else { _totalWeightedSupply -= uint128(decrease); } } // Update lock parameters _locks[tokenId].slope = newSlope; _locks[tokenId].lastUpdate = uint32(block.timestamp); } } _; } function getCurrentMultiplier(uint256 tokenId) public view returns (uint128) { LockPosition memory lock = _locks[tokenId]; if (uint32(block.timestamp) >= lock.endTime) return BASE_MULTIPLIER; // Calculate time-based multiplier - should be proportional to lock duration uint32 timeLeft = lock.endTime - uint32(block.timestamp); // Calculate how much of the maximum time is left (as a ratio) // This ensures amount doesn't affect multiplier, only duration does uint256 timeRatio = (uint256(timeLeft) * PRECISION) / MAXTIME; // Apply linear scaling between BASE_MULTIPLIER (1x) and MAX_MULTIPLIER (4x) uint256 multiplierCalc = BASE_MULTIPLIER + (uint256(MAX_MULTIPLIER - BASE_MULTIPLIER) * timeRatio) / PRECISION; uint128 multiplier = uint128(multiplierCalc); if (multiplier > MAX_MULTIPLIER) return MAX_MULTIPLIER; if (multiplier < BASE_MULTIPLIER) return BASE_MULTIPLIER; return multiplier; } function _checkpoint( uint256 tokenId, LockedBalance memory oldLocked, LockedBalance memory newLocked ) internal { _checkpointGlobal(); if (tokenId != 0) { _checkpointToken( tokenId, oldLocked, newLocked ); } } function _checkpointGlobal() internal { uint32 _epoch = epoch; Point memory lastPoint; // Get the last point if (_epoch > 0) { lastPoint = pointHistory[_epoch - 1]; } else { lastPoint = Point({ bias: 0, slope: 0, ts: uint32(block.timestamp), blk: uint32(block.number) }); } uint32 lastCheckpoint = lastPoint.ts; // Calculate block slope for time interpolation uint128 blockSlope = 0; if (uint32(block.timestamp) > lastCheckpoint) { blockSlope = uint128((PRECISION * (block.number - lastPoint.blk)) / (block.timestamp - lastPoint.ts)); } // Process weekly checkpoints lastPoint = _processWeeklyCheckpoints( lastPoint, lastCheckpoint, blockSlope, _epoch ); epoch = _epoch + 1; pointHistory[_epoch] = lastPoint; // Ensure we're not losing precision in the global state if (lastPoint.bias < 0) { lastPoint.bias = 0; } } function _processWeeklyCheckpoints( Point memory lastPoint, uint32 lastCheckpoint, uint128 blockSlope, uint32 _epoch ) internal returns (Point memory) { uint32 ti = (lastCheckpoint / WEEK) * WEEK; uint32 t = uint32(block.timestamp); for (uint256 i = 0; i < 255;) { ti += WEEK; if (ti > t) { lastPoint.bias -= lastPoint.slope * int128(uint128(t - lastCheckpoint)); lastPoint.ts = t; lastPoint.blk = uint32(block.number); break; } lastPoint.bias -= lastPoint.slope * int128(uint128(ti - lastCheckpoint)); lastPoint.slope += slopeChanges[ti]; lastPoint.ts = ti; lastPoint.blk = uint32(lastPoint.blk + (uint256(blockSlope) * (ti - lastPoint.ts)) / PRECISION); pointHistory[_epoch + 1 + uint32(i)] = lastPoint; lastCheckpoint = ti; unchecked { ++i; } } return lastPoint; } function _checkpointToken( uint256 tokenId, LockedBalance memory oldLocked, LockedBalance memory newLocked ) internal { Point memory uOld; Point memory uNew; _processLockPoint(oldLocked, uOld); _processLockPoint(newLocked, uNew); _processTokenSlopeChanges(oldLocked, newLocked, uOld.slope, uNew.slope); uint32 userEpoch = userPointEpoch[tokenId] + 1; userPointEpoch[tokenId] = userEpoch; uNew.ts = uint32(block.timestamp); uNew.blk = uint32(block.number); userPointHistory[tokenId][userEpoch] = uNew; } function _processLockPoint( LockedBalance memory locked, Point memory point ) internal view returns (bool) { if (locked.end <= uint32(block.timestamp) || locked.amount == 0) return false; uint256 timeLeft = uint256(locked.end - uint32(block.timestamp)); timeLeft = timeLeft > MAXTIME ? MAXTIME : timeLeft; uint256 multiplier = BASE_MULTIPLIER + ((timeLeft * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / MAXTIME); multiplier = multiplier > MAX_MULTIPLIER ? MAX_MULTIPLIER : multiplier < BASE_MULTIPLIER ? BASE_MULTIPLIER : multiplier; uint256 scaledAmount = uint256(uint128(locked.amount)); point.bias = int128(uint128((scaledAmount * multiplier) / PRECISION)); point.slope = int128(uint128((scaledAmount * PRECISION) / MAXTIME)); return true; } function _processTokenSlopeChanges( LockedBalance memory oldLocked, LockedBalance memory newLocked, int128 oldSlope, int128 newSlope ) internal { // Handle old lock slope changes if (oldLocked.end > uint32(block.timestamp)) { // Remove the old slope change int128 oldDslope = slopeChanges[oldLocked.end]; oldDslope += oldSlope; // Add because we're removing negative slope // If the new lock ends at the same time, we need to account for its slope too if (newLocked.end == oldLocked.end) { oldDslope -= newSlope; // Subtract new slope that will decrease at this time } slopeChanges[oldLocked.end] = oldDslope; } // Handle new lock slope changes if (newLocked.end > uint32(block.timestamp)) { if (newLocked.end > oldLocked.end) { // Only record new slope changes if the end time is different int128 newDslope = slopeChanges[newLocked.end]; newDslope -= newSlope; // This slope will decrease at the new end time slopeChanges[newLocked.end] = newDslope; } } } function transferFrom(address from, address to, uint256 tokenId) public virtual override { super.transferFrom(from,to, tokenId); } function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override { super.safeTransferFrom(from, to, tokenId, data); } function withdraw(uint256 tokenId) external nonReentrant whenNotPaused { address owner = _ownerOf(tokenId); if (owner == address(0)) revert TokenNotExists(); if (owner != msg.sender) revert NotTokenOwner(); LockPosition memory lock = _locks[tokenId]; if (lock.amount == 0) revert LockNotExists(); if (uint32(block.timestamp) < lock.endTime) revert LockNotExpired(); uint128 amount = lock.amount; // For expired locks, just subtract balance from weighted supply if (amount > _totalWeightedSupply) { _totalWeightedSupply = 0; } else { _totalWeightedSupply -= amount; } // Clear lock state delete _locks[tokenId]; // Create checkpoint data LockedBalance memory oldLock = LockedBalance({ amount: int128(uint128(amount)), end: lock.endTime }); // Checkpoint after clearing lock _checkpoint(tokenId, oldLock, LockedBalance(0, 0)); // Clean up remaining state delete userPointEpoch[tokenId]; // Transfer tokens before burning NFT _lockedToken.safeTransfer(msg.sender, amount); // Burn NFT last _burn(tokenId); unchecked { _userLockCount[msg.sender]--; } emit Withdraw(msg.sender, tokenId, amount); } function _calculateLockParameters( uint128 amount, uint32 lockDuration, uint128 minMultiplier ) internal pure returns (uint128 slope, uint128 multiplier) { // First divide by MAXTIME to avoid overflow uint256 slopeCalc = uint256(amount) / MAXTIME; // Then multiply by PRECISION slopeCalc = slopeCalc * PRECISION; require(slopeCalc <= type(uint128).max, "Slope overflow"); slope = uint128(slopeCalc); // Calculate multiplier multiplier = _calculateMultiplier(slope, lockDuration); if (multiplier > MAX_MULTIPLIER) revert MultiplierTooHigh(); if (multiplier < minMultiplier) revert SlippageExceeded(); } // Helper function to update weighted supply correctly for the poke operation // This is a differential update based on the change in multiplier function _updateWeightedSupply(uint256 tokenId, uint128 amount, uint128 newMultiplier) internal { // First calculate current weighted amount based on old multiplier LockPosition memory lock = _locks[tokenId]; // Calculate old multiplier using the same approach as _calculateMultiplier uint128 oldMultiplier; if (lock.endTime > uint32(block.timestamp)) { uint32 timeLeft = lock.endTime - uint32(block.timestamp); // Calculate time ratio first to avoid overflow uint256 timeRatio = (uint256(timeLeft) * PRECISION) / MAXTIME; // Calculate multiplier based on time ratio uint256 multiplierCalc = BASE_MULTIPLIER + ((timeRatio * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / PRECISION); if (multiplierCalc > MAX_MULTIPLIER) { oldMultiplier = MAX_MULTIPLIER; } else if (multiplierCalc < BASE_MULTIPLIER) { oldMultiplier = BASE_MULTIPLIER; } else { oldMultiplier = uint128(multiplierCalc); } } else { oldMultiplier = BASE_MULTIPLIER; } // Calculate old and new weighted amounts uint256 oldWeightedAmount = (uint256(amount) * uint256(oldMultiplier)) / PRECISION; uint256 newWeightedAmount = (uint256(amount) * uint256(newMultiplier)) / PRECISION; // Calculate the difference (can be positive or negative) if (newWeightedAmount > oldWeightedAmount) { uint256 increase = newWeightedAmount - oldWeightedAmount; if (increase > type(uint128).max) revert ArithmeticError(); _totalWeightedSupply += uint128(increase); } else if (oldWeightedAmount > newWeightedAmount) { uint256 decrease = oldWeightedAmount - newWeightedAmount; if (decrease > _totalWeightedSupply) { _totalWeightedSupply = 0; // Safeguard against underflow } else { _totalWeightedSupply -= uint128(decrease); } } // If equal, no change needed } function createLock( uint128 amount, uint32 lockDuration, uint256 deadline, uint128 minMultiplier ) external whenNotPaused validDeadline(deadline) returns (uint256 tokenId) { return createLockFor( msg.sender, amount, lockDuration, deadline, minMultiplier ); } function extendLock( uint256 tokenId, uint32 additionalDuration, uint256 deadline, uint128 minMultiplier ) external nonReentrant whenNotPaused validDeadline(deadline) poke(tokenId) { if (ownerOf(tokenId) != msg.sender) revert NotTokenOwner(); LockPosition memory lock = _locks[tokenId]; if (lock.amount == 0) revert LockNotExists(); uint32 newEndTime; if (lock.endTime < uint32(block.timestamp)) { // If lock is expired, extend from now newEndTime = uint32(block.timestamp) + additionalDuration; } else { // If lock is not expired, extend from current end time newEndTime = lock.endTime + additionalDuration; } uint32 totalRemainingDuration = newEndTime - uint32(block.timestamp); if (totalRemainingDuration > MAXTIME) revert InvalidDuration(); // Calculate new slope and multiplier with proper scaling uint128 newSlope = _calculateNewSlope(lock.amount); uint128 multiplier = _calculateMultiplier(newSlope, totalRemainingDuration); if (multiplier < minMultiplier) revert SlippageExceeded(); // Update weighted supply _updateWeightedSupply(tokenId, lock.amount, multiplier); // Checkpoint _checkpoint( tokenId, LockedBalance({ amount: int128(uint128(lock.amount)), end: lock.endTime }), LockedBalance({ amount: int128(uint128(lock.amount)), end: newEndTime }) ); // Update lock state _locks[tokenId] = LockPosition({ amount: lock.amount, endTime: newEndTime, lastUpdate: uint32(block.timestamp), slope: newSlope }); emit LockExtended(msg.sender, tokenId, newEndTime, multiplier); } function _calculateNewSlope(uint128 amount) private pure returns (uint128) { // First divide by MAXTIME to avoid overflow uint256 slopeCalc = uint256(amount) / MAXTIME; // Then multiply by PRECISION slopeCalc = slopeCalc * PRECISION; require(slopeCalc <= type(uint128).max, "Slope too high"); return uint128(slopeCalc); } function _calculateMultiplier(uint128 slope, uint32 duration) internal pure returns (uint128) { // Special case: If slope is 0, return base multiplier to avoid division by zero if (slope == 0) return BASE_MULTIPLIER; // Calculate time ratio first to avoid overflow uint256 timeRatio = (uint256(duration) * PRECISION) / MAXTIME; // Calculate multiplier based on time ratio uint256 multiplier = BASE_MULTIPLIER + ((timeRatio * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / PRECISION); if (multiplier > MAX_MULTIPLIER) return MAX_MULTIPLIER; if (multiplier < BASE_MULTIPLIER) return BASE_MULTIPLIER; return uint128(multiplier); } // Helper function for increasing lock amount logic function _processIncreaseLock( uint256 tokenId, uint128 additionalAmount, uint128 minMultiplier ) private { LockPosition storage lock = _locks[tokenId]; // Get old values and calculate new values uint128 oldAmount = lock.amount; uint128 newAmount = oldAmount + additionalAmount; uint32 endTime = lock.endTime; uint32 remainingDuration = endTime - uint32(block.timestamp); // Calculate new slope and multiplier uint128 newSlope = _calculateNewSlope(newAmount); uint128 multiplier = _calculateMultiplier(newSlope, remainingDuration); // Get current multiplier and use higher value uint128 currentMultiplier = getCurrentMultiplier(tokenId); multiplier = multiplier > currentMultiplier ? multiplier : currentMultiplier; // Slippage check for non-dust amounts if (additionalAmount > PRECISION / 1000 && multiplier < minMultiplier) { revert SlippageExceeded(); } // Checkpoint with correct LockedBalance structs _checkpoint( tokenId, LockedBalance({ amount: int128(uint128(oldAmount)), end: endTime }), LockedBalance({ amount: int128(uint128(newAmount)), end: endTime }) ); // Update lock state lock.amount = newAmount; lock.slope = newSlope; lock.lastUpdate = uint32(block.timestamp); // Update weighted supply _updateWeightedSupply(tokenId, additionalAmount, multiplier); emit AmountIncreased(msg.sender, tokenId, additionalAmount, newAmount, multiplier); } function increaseLockAmount( uint256 tokenId, uint128 additionalAmount, uint256 deadline, uint128 minMultiplier ) external nonReentrant whenNotPaused validDeadline(deadline) poke(tokenId) { // Basic validations if (ownerOf(tokenId) != tx.origin) {if (ownerOf(tokenId) != msg.sender) revert NotTokenOwner();} if (additionalAmount == 0) revert InvalidAmount(); // Check if lock exists and not expired LockPosition storage lock = _locks[tokenId]; if (lock.amount == 0) revert LockNotExists(); if (uint32(block.timestamp) >= lock.endTime) revert LockExpired(); // Transfer tokens uint256 balanceBefore = _lockedToken.balanceOf(address(this)); _lockedToken.safeTransferFrom(msg.sender, address(this), additionalAmount); if (_lockedToken.balanceOf(address(this)) != balanceBefore + additionalAmount) revert TransferFailed(); // Process the lock increase in a separate function _processIncreaseLock(tokenId, additionalAmount, minMultiplier); } function getTotalFarmingPower(uint32 timestamp) public view returns (uint128) { Point memory lastPoint = pointHistory[epoch]; return uint128(_supplyAt(lastPoint, timestamp)); } function _supplyAt(Point memory point, uint32 t) internal view returns (uint128) { uint32 ti = (point.ts / WEEK) * WEEK; for (uint256 i = 0; i < 255;) { ti += WEEK; if (ti > t) { point.bias -= point.slope * int128(uint128(t - point.ts)); break; } point.bias -= point.slope * int128(uint128(ti - point.ts)); point.slope += slopeChanges[ti]; point.ts = ti; unchecked { ++i; } } if (point.bias < 0) point.bias = 0; return uint128(uint256(uint128(point.bias))); } function _calculateMergeTotals( uint256[] calldata tokenIds ) private view returns (uint128 totalAmount, uint32 latestEndTime) { uint32 currentTime = uint32(block.timestamp); for (uint256 i = 0; i < tokenIds.length; i++) { if (ownerOf(tokenIds[i]) != msg.sender) revert NotTokenOwner(); LockPosition memory lock = _locks[tokenIds[i]]; if (lock.amount == 0) revert LockNotExists(); // Add the locked amount to the total totalAmount += lock.amount; // Only use end time if lock is not expired if (lock.endTime > currentTime && lock.endTime > latestEndTime) { latestEndTime = lock.endTime; } } // If all locks are expired, use current time as basis for new lock if (latestEndTime <= currentTime) { // Use minimum lock duration of 1 week (7 days) if all locks are expired latestEndTime = currentTime + 7 days; } } // Helper function for merge to process old tokens function _processOldTokens(uint256[] calldata tokenIds) private { for (uint256 i = 0; i < tokenIds.length; i++) { LockPosition memory lock = _locks[tokenIds[i]]; // Create checkpoint for old lock before clearing it LockedBalance memory oldLock = LockedBalance({ amount: int128(uint128(lock.amount)), end: lock.endTime }); // Checkpoint old token position with zeroed end state _checkpoint(tokenIds[i], oldLock, LockedBalance(0, 0)); // Now clear old lock state and burn token delete _locks[tokenIds[i]]; _burn(tokenIds[i]); } } function merge( uint256[] calldata tokenIds, uint256 deadline ) external nonReentrant whenNotPaused validDeadline(deadline) { if (tokenIds.length < 2) revert InvalidAmount(); // Calculate totals from all tokens while validating ownership uint128 totalAmount = 0; uint32 latestEndTime = 0; uint32 currentTime = uint32(block.timestamp); // First, validate and collect information for (uint256 i = 0; i < tokenIds.length; i++) { if (ownerOf(tokenIds[i]) != msg.sender) revert NotTokenOwner(); LockPosition memory lock = _locks[tokenIds[i]]; if (lock.amount == 0) revert LockNotExists(); // Add the locked amount to the total totalAmount += lock.amount; // Only use end time if lock is not expired if (lock.endTime > currentTime && lock.endTime > latestEndTime) { latestEndTime = lock.endTime; } // Calculate the weighted amount for this token and subtract from totalWeightedSupply uint128 tokenMultiplier = getCurrentMultiplier(tokenIds[i]); uint256 weightedAmount = (uint256(lock.amount) * tokenMultiplier) / PRECISION; if (weightedAmount > _totalWeightedSupply) { _totalWeightedSupply = 0; } else { _totalWeightedSupply -= uint128(weightedAmount); } } // If all locks are expired, use current time as basis for new lock if (latestEndTime <= currentTime) { // Use minimum lock duration of 1 week (7 days) if all locks are expired latestEndTime = currentTime + 7 days; } // Process old tokens before creating the new token for (uint256 i = 0; i < tokenIds.length; i++) { LockPosition memory lock = _locks[tokenIds[i]]; // Create checkpoint for old lock before clearing it LockedBalance memory oldLock = LockedBalance({ amount: int128(uint128(lock.amount)), end: lock.endTime }); // Checkpoint old token position with zeroed end state _checkpoint(tokenIds[i], oldLock, LockedBalance(0, 0)); // Now clear old lock state and burn token delete _locks[tokenIds[i]]; _burn(tokenIds[i]); } // Create new token with merged position uint32 newTokenId = _nextTokenId; while (_ownerOf(newTokenId) != address(0)) { unchecked { newTokenId++; } } // Update _nextTokenId to the next value after our used ID _nextTokenId = newTokenId + 1; // Mint new token _safeMint(msg.sender, newTokenId); // Calculate remaining duration and new slope uint32 remainingDuration = latestEndTime - currentTime; if (remainingDuration > MAXTIME) revert InvalidDuration(); uint128 newSlope = uint128((uint256(totalAmount) * PRECISION) / MAXTIME); // Create new lock state _locks[newTokenId] = LockPosition({ amount: totalAmount, endTime: latestEndTime, lastUpdate: currentTime, slope: newSlope }); // Create checkpoint data for new lock LockedBalance memory newLock = LockedBalance({ amount: int128(uint128(totalAmount)), end: latestEndTime }); // Checkpoint the new lock _checkpoint(newTokenId, LockedBalance(0, 0), newLock); // Calculate multiplier for new lock uint128 multiplier = _calculateMultiplier(newSlope, remainingDuration); // Update weighted supply by adding the new weighted amount uint256 newWeightedAmount = (uint256(totalAmount) * multiplier) / PRECISION; _totalWeightedSupply += uint128(newWeightedAmount); // Update user lock count unchecked { _userLockCount[msg.sender] = uint8(_userLockCount[msg.sender] - uint8(tokenIds.length) + 1); } emit Deposit(msg.sender, newTokenId, totalAmount, latestEndTime); } function getFarmingPower(uint256 tokenId, uint32 timestamp) public view returns (uint128) { // Get lock data first LockPosition memory lock = _locks[tokenId]; if (lock.amount == 0) return 0; // If timestamp is beyond lock end time, return base amount if (timestamp >= lock.endTime) return lock.amount; // If timestamp is before lock creation, return 0 if (timestamp < lock.lastUpdate) return 0; // Calculate time ratio and multiplier once uint256 timeRatio = (uint256(lock.endTime - timestamp) * PRECISION) / MAXTIME; uint256 multiplier = BASE_MULTIPLIER + ((timeRatio * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / PRECISION); multiplier = multiplier > MAX_MULTIPLIER ? MAX_MULTIPLIER : multiplier < BASE_MULTIPLIER ? BASE_MULTIPLIER : multiplier; // Calculate power once uint256 power = (uint256(lock.amount) * multiplier) / PRECISION; if (power > type(uint128).max) return type(uint128).max; // Get user epoch uint32 userEpoch = userPointEpoch[tokenId]; // Find the most recent point before the timestamp for (uint32 i = userEpoch; i >= 1; i--) { Point memory point = userPointHistory[tokenId][i]; if (point.ts <= timestamp) { // If point exists but has no bias, return calculated power if (point.bias == 0 && lock.amount > 0) { return uint128(power); } // Return the point's bias if it exists return uint128(uint256(uint128(point.bias))); } } // If no point found, return calculated power return uint128(power); } function getExpectedMultiplier(uint128 amount, uint32 duration) public pure returns (uint128) { if (duration == 0 || duration > MAXTIME) revert InvalidDuration(); if (amount == 0) revert InvalidAmount(); uint128 slope = uint128((uint256(amount) / MAXTIME) * PRECISION); return _calculateMultiplier(slope, duration); } function getMinMultiplier(uint128 amount, uint32 lockDuration) public view returns (uint128) { uint32 minDuration = lockDuration > MAX_BLOCK_DRIFT ? lockDuration - MAX_BLOCK_DRIFT : lockDuration; return getExpectedMultiplier(amount, minDuration); } // Emergency functions function enableEmergencyMode() external onlyOwner { _emergencyMode = true; _pause(); emit EmergencyModeEnabled(_emergencyRecoveryAddress); } function emergencyWithdraw(uint256 tokenId) external nonReentrant { require(_emergencyMode, "Not in emergency mode"); if (ownerOf(tokenId) != msg.sender) revert NotTokenOwner(); LockPosition memory lock = _locks[tokenId]; uint128 amount = lock.amount; delete _locks[tokenId]; _burn(tokenId); unchecked { _userLockCount[msg.sender]--; } _lockedToken.safeTransfer(msg.sender, amount); emit EmergencyWithdraw(msg.sender, tokenId, amount); } function unPause () external onlyOwner { _unpause(); } // View functions function getUserLockCount(address user) external view returns (uint8) { return _userLockCount[user]; } function lockedToken() external view returns (IERC20Upgradeable) { return _lockedToken; } function isEmergencyMode() external view returns (bool) { return _emergencyMode; } function totalWeightedSupply() external view returns (uint128) { return _totalWeightedSupply; } function setArtProxy(address _artProxy) external onlyOwner { if (_artProxy == address(0)) revert ZeroAddress(); artProxy = _artProxy; } function tokensForOwner(address owner) external view returns(uint256[] memory tokenIds) { uint8 count = _userLockCount[owner]; tokenIds = new uint256[](count); if (count == 0) return tokenIds; uint256 currentIndex = 0; for (uint256 id = 0; id < _nextTokenId; id++) { if (_ownerOf(id) == owner) { tokenIds[currentIndex] = id; currentIndex++; if (currentIndex >= count) break; } } return tokenIds; } function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (_ownerOf(tokenId) == address(0)) revert TokenNotExists(); if (artProxy == address(0)) revert InvalidArtProxy(); // Delegate tokenURI call to art proxy (bool success, bytes memory data) = artProxy.staticcall( abi.encodeWithSignature("tokenURI(uint256)", tokenId) ); require(success, "Art proxy call failed"); return abi.decode(data, (string)); } function createLockFor( address recipient, uint128 amount, uint32 lockDuration, uint256 deadline, uint128 minMultiplier ) public nonReentrant whenNotPaused validDeadline(deadline) returns (uint256 tokenId) { if (amount == 0) revert InvalidAmount(); if (lockDuration == 0 || lockDuration > MAXTIME) revert InvalidDuration(); if (recipient == address(0)) revert ZeroAddress(); if (_userLockCount[recipient] >= MAX_LOCKS_PER_USER) revert ExceedsMaxLocks(); uint32 unlockTime = uint32(block.timestamp) + lockDuration; (uint128 slope, uint128 multiplier) = _calculateLockParameters(amount, lockDuration, minMultiplier); // Create new lock balance LockedBalance memory newLock = LockedBalance({ amount: int128(uint128(amount)), end: unlockTime }); // Checkpoint before modifying state _checkpoint(0, LockedBalance(0, 0), newLock); // Transfer tokens using SafeERC20 uint256 balanceBefore = _lockedToken.balanceOf(address(this)); _lockedToken.safeTransferFrom(msg.sender, address(this), amount); if (_lockedToken.balanceOf(address(this)) != balanceBefore + amount) revert TransferFailed(); unchecked { tokenId = _nextTokenId++; _userLockCount[recipient]++; } _safeMint(recipient, tokenId); _locks[tokenId] = LockPosition({ amount: amount, endTime: unlockTime, lastUpdate: uint32(block.timestamp), slope: slope }); _updateWeightedSupply(tokenId, amount, multiplier); _checkpoint(tokenId, LockedBalance(0, 0), newLock); emit Deposit(recipient, tokenId, amount, unlockTime); } function pause() external onlyOwner { _pause(); } /** * @notice Recovers tokens from users who claimed rewards at the inflated rate * @dev Subtracts excess amounts from locks and transfers them back to rewards distributor * @param tokenIds Array of token IDs that claimed at inflated rate * @param amounts Array of excess amounts to recover from each token */ function resetTokenBalances( uint256[] calldata tokenIds, uint128[] calldata amounts ) external onlyOwner { require(tokenIds.length == amounts.length, "Array lengths must match"); for (uint256 i = 0; i < tokenIds.length;) { uint256 tokenId = tokenIds[i]; if (_ownerOf(tokenId) == address(0)) { unchecked { ++i; } continue; } LockPosition memory lock = _locks[tokenId]; if (lock.amount > 0) { uint128 amountToSubtract = amounts[i]; if (amountToSubtract > 0) { uint128 multiplier = getCurrentMultiplier(tokenId); uint256 oldWeightedAmount = (uint256(lock.amount) * multiplier) / PRECISION; uint256 newWeightedAmount = (uint256(lock.amount - amountToSubtract) * multiplier) / PRECISION; if (oldWeightedAmount > _totalWeightedSupply) { _totalWeightedSupply = 0; } else { _totalWeightedSupply -= uint128(oldWeightedAmount); } _totalWeightedSupply += uint128(newWeightedAmount); _locks[tokenId].amount -= amountToSubtract; _locks[tokenId].slope = uint128((uint256(lock.amount - amountToSubtract) * PRECISION) / MAXTIME); _checkpoint(tokenId, LockedBalance({amount: int128(uint128(lock.amount)), end: lock.endTime}), LockedBalance({amount: int128(uint128(lock.amount - amountToSubtract)), end: lock.endTime}) ); // Transfer recovered tokens back to rewards distributor IERC20Upgradeable(address(_lockedToken)).safeTransfer(address(_distributor), amountToSubtract); } } unchecked { ++i; } } _checkpointGlobal(); } /** * @notice Calculates the total amount of tokens that are locked in the contract * @return The total locked balance */ function getTotalLockedBalance() public view returns (uint256) { uint256 totalLocked = 0; // Iterate through all tokens and sum their locked amounts for (uint256 i = 0; i < _nextTokenId; i++) { if (_ownerOf(i) != address(0)) { // Check if token exists totalLocked += _locks[i].amount; } } return totalLocked; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArithmeticError","type":"error"},{"inputs":[],"name":"DeadlineExpired","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[],"name":"ExceedsMaxLocks","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidArtProxy","type":"error"},{"inputs":[],"name":"InvalidDuration","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidMultiplier","type":"error"},{"inputs":[],"name":"InvalidRewardRate","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"LockExpired","type":"error"},{"inputs":[],"name":"LockNotExists","type":"error"},{"inputs":[],"name":"LockNotExpired","type":"error"},{"inputs":[],"name":"MaxRewardRateExceeded","type":"error"},{"inputs":[],"name":"MultiplierTooHigh","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NotTokenOwner","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"SlippageExceeded","type":"error"},{"inputs":[],"name":"TokenNotExists","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroReward","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"additionalAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"newTotalAmount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"newMultiplier","type":"uint128"}],"name":"AmountIncreased","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":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"lockTime","type":"uint32"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recoveryAddress","type":"address"}],"name":"EmergencyModeEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"newEndTime","type":"uint32"},{"indexed":false,"internalType":"uint128","name":"newMultiplier","type":"uint128"}],"name":"LockExtended","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"reward","type":"uint128"}],"name":"RewardClaimed","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":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_locks","outputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint128","name":"slope","type":"uint128"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"lastUpdate","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_userLockCount","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"artProxy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint32","name":"lockDuration","type":"uint32"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint128","name":"minMultiplier","type":"uint128"}],"name":"createLock","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint32","name":"lockDuration","type":"uint32"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint128","name":"minMultiplier","type":"uint128"}],"name":"createLockFor","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableEmergencyMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint32","name":"additionalDuration","type":"uint32"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint128","name":"minMultiplier","type":"uint128"}],"name":"extendLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getCurrentMultiplier","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint32","name":"duration","type":"uint32"}],"name":"getExpectedMultiplier","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint32","name":"timestamp","type":"uint32"}],"name":"getFarmingPower","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint32","name":"lockDuration","type":"uint32"}],"name":"getMinMultiplier","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"timestamp","type":"uint32"}],"name":"getTotalFarmingPower","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalLockedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserLockCount","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint128","name":"additionalAmount","type":"uint128"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint128","name":"minMultiplier","type":"uint128"}],"name":"increaseLockAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lockedToken_","type":"address"},{"internalType":"address","name":"emergencyRecovery","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isEmergencyMode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockedToken","outputs":[{"internalType":"contract IERC20Upgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"merge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"pointHistory","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint32","name":"ts","type":"uint32"},{"internalType":"uint32","name":"blk","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint128[]","name":"amounts","type":"uint128[]"}],"name":"resetTokenBalances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_artProxy","type":"address"}],"name":"setArtProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"distributor_","type":"address"}],"name":"setDistributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"slopeChanges","outputs":[{"internalType":"int128","name":"","type":"int128"}],"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":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensForOwner","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalWeightedSupply","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"userPointEpoch","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"userPointHistory","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint32","name":"ts","type":"uint32"},{"internalType":"uint32","name":"blk","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052606d805463ffffffff60a01b1916600f60a01b1790553480156024575f5ffd5b50602b602f565b60df565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615607e5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460dc5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b615e12806100ec5f395ff3fe608060405234801561000f575f5ffd5b50600436106102ad575f3560e01c806389f839c61161016c578063beb83109116100d5578063ddacc94a1161008f578063ddacc94a1461076b578063df0c78ef1461077e578063df21515714610791578063e58f5947146107a4578063e985e9c5146107c9578063f2fde38b146107dc578063f7b188a5146107ef575f5ffd5b8063beb831091461070f578063c5b1c7d014610722578063c71820101461072a578063c87b56dd1461073d578063d5c2589014610750578063d89dd26914610758575f5ffd5b806397612d4b1161012657806397612d4b146106645780639b7d02ad14610677578063a22cb465146106b4578063b88d4fde146106c7578063bbe33ea5146106da578063bcc00225146106ed575f5ffd5b806389f839c6146105525780638b25e8c1146105d55780638da5cb5b146105e85780638ff42490146105f0578063900cf0cf1461063757806395d89b411461065c575f5ffd5b80632a90752d11610219578063586c2600116101d3578063586c2600146104c95780635c975abb146104fe5780636352211e1461050957806370a082311461051c578063715018a61461052f57806375619ab5146105375780638456cb591461054a575f5ffd5b80632a90752d146104495780632e1a7d4d1461046a5780632e720f7d1461047d57806342842e0e146104905780635312ea8e146104a35780635594a045146104b6575f5ffd5b80631d237a491161026a5780631d237a49146103545780631f5ab022146103d95780632016a0d2146103ec57806320a194b8146103ff57806323b872dd14610411578063268dc19914610424575f5ffd5b806301ffc9a7146102b157806306fdde03146102d9578063081812fc146102ee578063095ea7b31461030e5780630f45cc811461032357806313de148b14610334575b5f5ffd5b6102c46102bf366004615370565b6107f7565b60405190151581526020015b60405180910390f35b6102e1610848565b6040516102d091906153b9565b6103016102fc3660046153cb565b6108e5565b6040516102d091906153e2565b61032161031c366004615411565b6108f9565b005b6064546001600160a01b0316610301565b610347610342366004615439565b610908565b6040516102d09190615452565b6103a66103623660046154a7565b606b60209081525f928352604080842090915290825290208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b60408051600f95860b81529390940b602084015263ffffffff9182169383019390935290911660608201526080016102d0565b6103216103e73660046154e7565b6109fc565b6103216103fa3660046155ed565b6111af565b606f54600160a01b900460ff166102c4565b61032161041f366004615670565b6113a6565b606e546001600160801b03165b6040516001600160801b0390911681526020016102d0565b61045c6104573660046156aa565b6113b6565b6040519081526020016102d0565b6103216104783660046153cb565b6117d4565b61032161048b366004615439565b611a6f565b61032161049e366004615670565b611ac0565b6103216104b13660046153cb565b611ada565b606d54610301906001600160a01b031681565b6104eb6104d7366004615704565b606c6020525f9081526040902054600f0b81565b604051600f9190910b81526020016102d0565b60325460ff166102c4565b6103016105173660046153cb565b611c72565b61045c61052a366004615439565b611c7c565b610321611cd1565b610321610545366004615439565b611ce4565b610321611d88565b61059e6105603660046153cb565b60666020525f9081526040902080546001909101546001600160801b0380831692600160801b9004169063ffffffff80821691600160201b90041684565b604080516001600160801b03958616815294909316602085015263ffffffff918216928401929092521660608201526080016102d0565b6104316105e33660046153cb565b611d98565b610301611ef6565b6103a66105fe366004615704565b60686020525f908152604090208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b6069546106479063ffffffff1681565b60405163ffffffff90911681526020016102d0565b6102e1611f24565b610431610672366004615704565b611f40565b6106a2610685366004615439565b6001600160a01b03165f9081526067602052604090205460ff1690565b60405160ff90911681526020016102d0565b6103216106c236600461572a565b611fac565b6103216106d536600461575f565b611fb7565b6103216106e8366004615810565b611fc3565b6106a26106fb366004615439565b60676020525f908152604090205460ff1681565b61032161071d366004615857565b612683565b610321612d24565b61032161073836600461587a565b612d8e565b6102e161074b3660046153cb565b61314c565b61045c61329f565b6104316107663660046158e4565b613304565b6104316107793660046154a7565b61339d565b61043161078c3660046158e4565b613654565b61045c61079f36600461590c565b61369e565b6106476107b23660046153cb565b606a6020525f908152604090205463ffffffff1681565b6102c46107d7366004615936565b6136d6565b6103216107ea366004615439565b613713565b61032161374d565b5f6001600160e01b031982166380ac58cd60e01b148061082757506001600160e01b03198216635b5e139f60e01b145b8061084257506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f61085361375d565b9050805f0180546108639061595e565b80601f016020809104026020016040519081016040528092919081815260200182805461088f9061595e565b80156108da5780601f106108b1576101008083540402835291602001916108da565b820191905f5260205f20905b8154815290600101906020018083116108bd57829003601f168201915b505050505091505090565b5f6108ef82613781565b50610842826137b8565b6109048282336137df565b5050565b6001600160a01b0381165f9081526067602052604090205460609060ff16806001600160401b0381111561093e5761093e61552a565b604051908082528060200260200182016040528015610967578160200160208202803683370190505b5091508060ff165f0361097a5750919050565b5f805b606554600160a01b900463ffffffff168110156109f457846001600160a01b03166109a7826137ec565b6001600160a01b0316036109ec57808483815181106109c8576109c8615990565b6020908102919091010152816109dd816159b8565b9250508260ff168210156109f4575b60010161097d565b505050919050565b610a04613813565b610a0c61386a565b8180421115610a2e57604051631ab7da6b60e01b815260040160405180910390fd5b5f85815260666020908152604091829020825160808101845281546001600160801b03808216808452600160801b909204169382019390935260019091015463ffffffff80821694830194909452600160201b9004909216606083015286919015801590610aab5750806040015163ffffffff164263ffffffff16105b15610e75575f428260400151610ac191906159d0565b90505f62ed4e00610ae0670de0b6b3a764000063ffffffff85166159ec565b610aea9190615a17565b90505f670de0b6b3a764000082610b0982673782dace9d900000615a2a565b6001600160801b0316610b1c91906159ec565b610b269190615a17565b610b3890670de0b6b3a7640000615a49565b905080673782dace9d9000006001600160801b0382161115610b5f5750673782dace9d9000005b670de0b6b3a76400006001600160801b0382161015610b835750670de0b6b3a76400005b84515f90670de0b6b3a764000090610ba89062ed4e00906001600160801b0316615a17565b610bb291906159ec565b90505f819050806001600160801b031687602001516001600160801b0316141580610bf4575062015180876060015163ffffffff1642610bf29190615a5c565b115b15610e6e5760208701515f906001600160801b031615610cd9575f62ed4e00610c2b670de0b6b3a764000063ffffffff8b166159ec565b610c359190615a17565b90505f670de0b6b3a764000082610c5482673782dace9d900000615a2a565b6001600160801b0316610c6791906159ec565b610c719190615a17565b610c8390670de0b6b3a7640000615a49565b9250829050673782dace9d9000006001600160801b0382161115610cad57673782dace9d90000092505b670de0b6b3a76400006001600160801b0384161015610cd257670de0b6b3a764000092505b5050610ce4565b50670de0b6b3a76400005b87515f90670de0b6b3a764000090610d08906001600160801b0385811691166159ec565b610d129190615a17565b89519091505f90670de0b6b3a764000090610d39906001600160801b0389811691166159ec565b610d439190615a17565b905081811115610da1575f610d588383615a5c565b606e805491925082915f90610d779084906001600160801b0316615a6f565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555050610e23565b80821115610e23575f610db48284615a5c565b606e549091506001600160801b0316811115610ddf57606e80546001600160801b0319169055610e21565b606e80548291905f90610dfc9084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b505b5050505f88815260666020526040902080546001600160801b03808416600160801b029116178155600101805463ffffffff4216600160201b0267ffffffff00000000199091161790555b5050505050505b33610e7f88611c72565b6001600160a01b031614610ea6576040516359dc379f60e01b815260040160405180910390fd5b5f878152606660209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b900490911660608201529103610f2157604051632254ea3d60e11b815260040160405180910390fd5b5f4263ffffffff16826040015163ffffffff161015610f4b57610f448842615a8e565b9050610f5e565b878260400151610f5b9190615a8e565b90505b5f610f6942836159d0565b905062ed4e0063ffffffff82161115610f9557604051637616640160e01b815260040160405180910390fd5b5f610fa2845f01516138b0565b90505f610faf8284613926565b9050886001600160801b0316816001600160801b03161015610fe457604051638199f5f360e01b815260040160405180910390fd5b610ff28c865f015183613a00565b6110418c6040518060400160405280885f0151600f0b8152602001886040015163ffffffff168152506040518060400160405280895f0151600f0b81526020018863ffffffff16815250613caa565b6040518060800160405280865f01516001600160801b03168152602001836001600160801b031681526020018563ffffffff1681526020014263ffffffff1681525060665f8e81526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055509050508b336001600160a01b03167f3032be442129e161b4ae1cdee94871a69de2c16ee2007f31fc209a715673455c868460405161119092919063ffffffff9290921682526001600160801b0316602082015260400190565b60405180910390a350505050505050506111a960015f55565b50505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f811580156111f35750825b90505f826001600160401b0316600114801561120e5750303b155b90508115801561121c575080155b1561123a5760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b0319166001178555831561126357845460ff60401b1916600160401b1785555b6001600160a01b038916158061128057506001600160a01b038816155b1561129e5760405163d92e233d60e01b815260040160405180910390fd5b6112a88787613cc9565b6112b0613cdb565b6112b8613ceb565b6112c133613cfb565b6112c9613d0c565b606480546001600160a01b03808c166001600160a01b031992831617909255606f8054928b16929091169190911790555f805260686020527fad6f8124f6081c2622ab3a16acd47af73d52fe87b755c3f897263c58ba3fdbd880544263ffffffff90811663ffffffff194392909216600160201b02919091166001600160401b031990921691909117179055831561139b57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b6113b1838383613d56565b505050565b5f6113bf613813565b6113c761386a565b82804211156113e957604051631ab7da6b60e01b815260040160405180910390fd5b856001600160801b03165f036114125760405163162908e360e11b815260040160405180910390fd5b63ffffffff8516158061142d575062ed4e0063ffffffff8616115b1561144b57604051637616640160e01b815260040160405180910390fd5b6001600160a01b0387166114725760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0387165f90815260676020526040902054606460ff909116106114af5760405163133cbc4f60e01b815260040160405180910390fd5b5f6114ba8642615a8e565b90505f5f6114c9898988613dd9565b915091505f60405180604001604052808b600f0b81526020018563ffffffff1681525090506115165f60405180604001604052805f600f0b81526020015f63ffffffff1681525083613caa565b6064546040516370a0823160e01b81525f916001600160a01b0316906370a08231906115469030906004016153e2565b602060405180830381865afa158015611561573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115859190615aaa565b6064549091506115a9906001600160a01b031633306001600160801b038f16613ecd565b6115bc6001600160801b038c1682615a49565b6064546040516370a0823160e01b81526001600160a01b03909116906370a08231906115ec9030906004016153e2565b602060405180830381865afa158015611607573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061162b9190615aaa565b14611649576040516312171d8360e31b815260040160405180910390fd5b60658054600163ffffffff600160a01b80840482168381019092160263ffffffff60a01b19909316929092179092556001600160a01b038e165f908152606760205260409020805460ff80821690940190931660ff199093169290921790915596506116b58c88613f38565b604080516080810182526001600160801b03808e168252868116602080840191825263ffffffff808b16858701908152428216606087019081525f8f8152606690945296909220945192518416600160801b0292909316919091178355516001909201805493518216600160201b026001600160401b03199094169290911691909117919091179055611749878c85613a00565b604080518082019091525f808252602082015261176890889084613caa565b604080516001600160801b038d16815263ffffffff8716602082015288916001600160a01b038f16917fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f8597828934954910160405180910390a35050505050506117cb60015f55565b95945050505050565b6117dc613813565b6117e461386a565b5f6117ee826137ec565b90506001600160a01b03811661181657604051626f708760e21b815260040160405180910390fd5b6001600160a01b038116331461183f576040516359dc379f60e01b815260040160405180910390fd5b5f828152606660209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b9004909116606082015291036118ba57604051632254ea3d60e11b815260040160405180910390fd5b806040015163ffffffff164263ffffffff1610156118eb5760405163342ad40160e11b815260040160405180910390fd5b8051606e546001600160801b03908116908216111561191957606e80546001600160801b031916905561195b565b606e80548291905f906119369084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b5f84815260666020908152604080832083815560010180546001600160401b031916905580518082018252600f85900b81528582015163ffffffff1681840152815180830190925283825291810192909252906119bb9086908390613caa565b5f858152606a60205260409020805463ffffffff191690556064546119f3906001600160a01b0316336001600160801b038516613f51565b6119fc85613f81565b335f81815260676020908152604091829020805460ff19811660ff9182165f190190911617905590516001600160801b03851681528792917f8903a5b5d08a841e7f68438387f1da20c84dea756379ed37e633ff3854b99b84910160405180910390a350505050611a6c60015f55565b50565b611a77613fb9565b6001600160a01b038116611a9e5760405163d92e233d60e01b815260040160405180910390fd5b606d80546001600160a01b0319166001600160a01b0392909216919091179055565b6113b183838360405180602001604052805f815250611fb7565b611ae2613813565b606f54600160a01b900460ff16611b385760405162461bcd60e51b81526020600482015260156024820152744e6f7420696e20656d657267656e6379206d6f646560581b60448201526064015b60405180910390fd5b33611b4282611c72565b6001600160a01b031614611b69576040516359dc379f60e01b815260040160405180910390fd5b5f818152606660208181526040808420815160808101835281546001600160801b03808216808452600160801b909204168286015260018301805463ffffffff80821696850196909652600160201b81049095166060840152888852959094529490556001600160401b031916909155611be283613f81565b335f818152606760205260409020805460ff19811660ff9182165f1901909116179055606454611c27916001600160a01b03909116906001600160801b038416613f51565b6040516001600160801b0382168152839033907f4f27eb511b2a4633cfb633ac1c4a99b4c298ca6488b29ec26f3504a5927f67289060200160405180910390a35050611a6c60015f55565b5f61084282613781565b5f5f611c8661375d565b90506001600160a01b038316611cb1575f6040516322718ad960e21b8152600401611b2f91906153e2565b6001600160a01b039092165f908152600390920160205250604090205490565b611cd9613fb9565b611ce25f613feb565b565b611cec613fb9565b6001600160a01b038116611d135760405163d92e233d60e01b815260040160405180910390fd5b6065546001600160a01b031615611d665760405162461bcd60e51b8152602060048201526017602482015276111a5cdd1c9a589d5d1bdc88185b1c9958591e481cd95d604a1b6044820152606401611b2f565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b611d90613fb9565b611ce2613d0c565b5f818152606660209081526040808320815160808101835281546001600160801b038082168352600160801b90910416938101939093526001015463ffffffff808216928401839052600160201b90910481166060840152421610611e075750670de0b6b3a764000092915050565b5f428260400151611e1891906159d0565b90505f62ed4e00611e37670de0b6b3a764000063ffffffff85166159ec565b611e419190615a17565b90505f670de0b6b3a764000082611e6082673782dace9d900000615a2a565b6001600160801b0316611e7391906159ec565b611e7d9190615a17565b611e8f90670de0b6b3a7640000615a49565b905080673782dace9d9000006001600160801b0382161115611ebf5750673782dace9d9000009695505050505050565b670de0b6b3a76400006001600160801b0382161015611eec5750670de0b6b3a76400009695505050505050565b9695505050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b60605f611f2f61375d565b90508060010180546108639061595e565b60695463ffffffff9081165f90815260686020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001015480851691830191909152600160201b9004909216606083015290611fa5818461405b565b9392505050565b610904338383614191565b6111a984848484614234565b611fcb613813565b611fd361386a565b8080421115611ff557604051631ab7da6b60e01b815260040160405180910390fd5b60028310156120175760405163162908e360e11b815260040160405180910390fd5b5f8042815b86811015612221573361204689898481811061203a5761203a615990565b90506020020135611c72565b6001600160a01b03161461206d576040516359dc379f60e01b815260040160405180910390fd5b5f60665f8a8a8581811061208357612083615990565b602090810292909201358352508181019290925260409081015f908120825160808101845281546001600160801b03808216808452600160801b909204169582019590955260019091015463ffffffff80821694830194909452600160201b900490921660608301529092500361210d57604051632254ea3d60e11b815260040160405180910390fd5b80516121199086615a6f565b94508263ffffffff16816040015163ffffffff1611801561214957508363ffffffff16816040015163ffffffff16115b1561215657806040015193505b5f6121788a8a8581811061216c5761216c615990565b90506020020135611d98565b82519091505f90670de0b6b3a76400009061219f906001600160801b0380861691166159ec565b6121a99190615a17565b606e549091506001600160801b03168111156121d457606e80546001600160801b0319169055612216565b606e80548291905f906121f19084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b50505060010161201c565b508063ffffffff168263ffffffff1611612245576122428162093a80615a8e565b91505b5f5b86811015612391575f60665f8a8a8581811061226557612265615990565b602090810292909201358352508181019290925260409081015f20815160808101835281546001600160801b038082168352600160801b909104168185015260019091015463ffffffff808216838501908152600160201b9092048116606084015283518085019094528251600f0b8452905116928201929092529091506123238a8a858181106122f8576122f8615990565b905060200201358260405180604001604052805f600f0b81526020015f63ffffffff16815250613caa565b60665f8b8b8681811061233857612338615990565b602090810292909201358352508101919091526040015f90812090815560010180546001600160401b03191690556123878a8a8581811061237b5761237b615990565b90506020020135613f81565b5050600101612247565b50606554600160a01b900463ffffffff165b5f6123b363ffffffff83166137ec565b6001600160a01b0316146123c9576001016123a3565b6123d4816001615a8e565b6065805463ffffffff60a01b1916600160a01b63ffffffff938416021790556124009033908316613f38565b5f61240b83856159d0565b905062ed4e0063ffffffff8216111561243757604051637616640160e01b815260040160405180910390fd5b5f62ed4e00612457670de0b6b3a76400006001600160801b0389166159ec565b6124619190615a17565b604080516080810182526001600160801b03808a168252808416602080840191825263ffffffff808c168587018181528c8316606088019081528c84165f818152606687528a8120995197518916600160801b029790981696909617885590516001909701805491518416600160201b026001600160401b0319909216979093169690961795909517905584518086018652600f8d900b8152808201949094528451808601909552828552840191909152929350916125209183613caa565b5f61252b8385613926565b90505f670de0b6b3a764000061254d6001600160801b03808516908c166159ec565b6125579190615a17565b606e805491925082915f906125769084906001600160801b0316615a6f565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508c8c905060675f336001600160a01b03166001600160a01b031681526020019081526020015f205f9054906101000a900460ff160360010160675f336001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055508563ffffffff16336001600160a01b03167fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f85978289349548b8b6040516126689291906001600160801b0392909216825263ffffffff16602082015260400190565b60405180910390a3505050505050505050506113b160015f55565b61268b613813565b61269361386a565b81804211156126b557604051631ab7da6b60e01b815260040160405180910390fd5b5f85815260666020908152604091829020825160808101845281546001600160801b03808216808452600160801b909204169382019390935260019091015463ffffffff80821694830194909452600160201b90049092166060830152869190158015906127325750806040015163ffffffff164263ffffffff16105b15612afc575f42826040015161274891906159d0565b90505f62ed4e00612767670de0b6b3a764000063ffffffff85166159ec565b6127719190615a17565b90505f670de0b6b3a76400008261279082673782dace9d900000615a2a565b6001600160801b03166127a391906159ec565b6127ad9190615a17565b6127bf90670de0b6b3a7640000615a49565b905080673782dace9d9000006001600160801b03821611156127e65750673782dace9d9000005b670de0b6b3a76400006001600160801b038216101561280a5750670de0b6b3a76400005b84515f90670de0b6b3a76400009061282f9062ed4e00906001600160801b0316615a17565b61283991906159ec565b90505f819050806001600160801b031687602001516001600160801b031614158061287b575062015180876060015163ffffffff16426128799190615a5c565b115b15612af55760208701515f906001600160801b031615612960575f62ed4e006128b2670de0b6b3a764000063ffffffff8b166159ec565b6128bc9190615a17565b90505f670de0b6b3a7640000826128db82673782dace9d900000615a2a565b6001600160801b03166128ee91906159ec565b6128f89190615a17565b61290a90670de0b6b3a7640000615a49565b9250829050673782dace9d9000006001600160801b038216111561293457673782dace9d90000092505b670de0b6b3a76400006001600160801b038416101561295957670de0b6b3a764000092505b505061296b565b50670de0b6b3a76400005b87515f90670de0b6b3a76400009061298f906001600160801b0385811691166159ec565b6129999190615a17565b89519091505f90670de0b6b3a7640000906129c0906001600160801b0389811691166159ec565b6129ca9190615a17565b905081811115612a28575f6129df8383615a5c565b606e805491925082915f906129fe9084906001600160801b0316615a6f565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555050612aaa565b80821115612aaa575f612a3b8284615a5c565b606e549091506001600160801b0316811115612a6657606e80546001600160801b0319169055612aa8565b606e80548291905f90612a839084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b505b5050505f88815260666020526040902080546001600160801b03808416600160801b029116178155600101805463ffffffff4216600160201b0267ffffffff00000000199091161790555b5050505050505b32612b0688611c72565b6001600160a01b031614612b455733612b1e88611c72565b6001600160a01b031614612b45576040516359dc379f60e01b815260040160405180910390fd5b856001600160801b03165f03612b6e5760405163162908e360e11b815260040160405180910390fd5b5f878152606660205260408120805490916001600160801b039091169003612ba957604051632254ea3d60e11b815260040160405180910390fd5b600181015463ffffffff9081164290911610612bd8576040516307b7d7dd60e51b815260040160405180910390fd5b6064546040516370a0823160e01b81525f916001600160a01b0316906370a0823190612c089030906004016153e2565b602060405180830381865afa158015612c23573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c479190615aaa565b606454909150612c6b906001600160a01b031633306001600160801b038c16613ecd565b612c7e6001600160801b03891682615a49565b6064546040516370a0823160e01b81526001600160a01b03909116906370a0823190612cae9030906004016153e2565b602060405180830381865afa158015612cc9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ced9190615aaa565b14612d0b576040516312171d8360e31b815260040160405180910390fd5b612d1689898861424c565b50505050506111a960015f55565b612d2c613fb9565b606f805460ff60a01b1916600160a01b179055612d47613d0c565b606f546040517fc0a1c7e9f05b4d536e1ff8606bae9b847cdb43ef4a9b2d7a503a88cee08dccdb91612d84916001600160a01b03909116906153e2565b60405180910390a1565b612d96613fb9565b828114612de05760405162461bcd60e51b8152602060048201526018602482015277082e4e4c2f240d8cadccee8d0e640daeae6e840dac2e8c6d60431b6044820152606401611b2f565b5f5b83811015613143575f858583818110612dfd57612dfd615990565b9050602002013590505f6001600160a01b0316612e19826137ec565b6001600160a01b031603612e305750600101612de2565b5f81815260666020908152604091829020825160808101845281546001600160801b03808216808452600160801b909204169382019390935260019091015463ffffffff80821694830194909452600160201b9004909216606083015215613139575f858585818110612ea557612ea5615990565b9050602002016020810190612eba9190615ac1565b90506001600160801b03811615613137575f612ed584611d98565b83519091505f90670de0b6b3a764000090612efc906001600160801b0380861691166159ec565b612f069190615a17565b90505f670de0b6b3a76400006001600160801b0316836001600160801b031685875f0151612f349190615a2a565b6001600160801b0316612f4791906159ec565b612f519190615a17565b606e549091506001600160801b0316821115612f7c57606e80546001600160801b0319169055612fbe565b606e80548391905f90612f999084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b606e80548291905f90612fdb9084906001600160801b0316615a6f565b82546101009290920a6001600160801b038181021990931691831602179091555f8881526066602052604081208054889450909261301b91859116615a2a565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555062ed4e0063ffffffff16670de0b6b3a76400006001600160801b031685875f015161306a9190615a2a565b6001600160801b031661307d91906159ec565b6130879190615a17565b5f8781526066602090815260409182902080546001600160801b03948516600160801b02941693909317909255805180820182528751600f0b81528782015163ffffffff16928101929092528051808201909152865161310d928992909181906130f2908a90615a2a565b600f0b8152602001896040015163ffffffff16815250613caa565b606554606454613133916001600160a01b0391821691166001600160801b038716613f51565b5050505b505b5050600101612de2565b506111a961441f565b60605f613158836137ec565b6001600160a01b03160361317e57604051626f708760e21b815260040160405180910390fd5b606d546001600160a01b03166131a7576040516338a69c8d60e21b815260040160405180910390fd5b606d54604051602481018490525f9182916001600160a01b039091169060440160408051601f198184030181529181526020820180516001600160e01b031663c87b56dd60e01b179052516131fc9190615ada565b5f60405180830381855afa9150503d805f8114613234576040519150601f19603f3d011682016040523d82523d5f602084013e613239565b606091505b5091509150816132835760405162461bcd60e51b8152602060048201526015602482015274105c9d081c1c9bde1e4818d85b1b0819985a5b1959605a1b6044820152606401611b2f565b808060200190518101906132979190615af0565b949350505050565b5f80805b606554600160a01b900463ffffffff168110156132fe575f6132c4826137ec565b6001600160a01b0316146132f6575f818152606660205260409020546132f3906001600160801b031683615a49565b91505b6001016132a3565b50919050565b5f63ffffffff82161580613320575062ed4e0063ffffffff8316115b1561333e57604051637616640160e01b815260040160405180910390fd5b826001600160801b03165f036133675760405163162908e360e11b815260040160405180910390fd5b5f670de0b6b3a764000061338762ed4e006001600160801b038716615a17565b61339191906159ec565b90506132978184613926565b5f828152606660209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b90049091166060820152908203613409575f915050610842565b806040015163ffffffff168363ffffffff161061342857519050610842565b806060015163ffffffff168363ffffffff161015613449575f915050610842565b60408101515f9062ed4e0090670de0b6b3a76400009061346a9087906159d0565b63ffffffff1661347a91906159ec565b6134849190615a17565b90505f670de0b6b3a76400006134a281673782dace9d900000615a2a565b6134b5906001600160801b0316846159ec565b6134bf9190615a17565b6134d190670de0b6b3a7640000615a49565b9050673782dace9d900000811161350557670de0b6b3a764000081106134f7578061350f565b670de0b6b3a764000061350f565b673782dace9d9000005b83519091505f90670de0b6b3a7640000906135349084906001600160801b03166159ec565b61353e9190615a17565b90506001600160801b03811115613562576001600160801b03945050505050610842565b5f878152606a602052604090205463ffffffff16805b60018163ffffffff1610613647575f898152606b6020908152604080832063ffffffff80861685529083529281902081516080810183528154600f81810b8352600160801b909104900b9381019390935260010154808416918301829052600160201b90048316606083015290918a1610613634578051600f0b158015613608575086516001600160801b031615155b1561361c5783975050505050505050610842565b516001600160801b0316965061084295505050505050565b508061363f81615b64565b915050613578565b5090979650505050505050565b606d545f90819063ffffffff600160a01b9091048116908416116136785782613692565b606d5461369290600160a01b900463ffffffff16846159d0565b90506132978482613304565b5f6136a761386a565b82804211156136c957604051631ab7da6b60e01b815260040160405180910390fd5b611eec33878787876113b6565b5f5f6136e061375d565b6001600160a01b039485165f90815260059190910160209081526040808320959096168252939093525050205460ff1690565b61371b613fb9565b6001600160a01b038116613744575f604051631e4fbdf760e01b8152600401611b2f91906153e2565b611a6c81613feb565b613755613fb9565b611ce26145e0565b7f80bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab007930090565b5f5f61378c836137ec565b90506001600160a01b03811661084257604051637e27328960e01b815260048101849052602401611b2f565b5f5f6137c261375d565b5f938452600401602052505060409020546001600160a01b031690565b6113b18383836001614619565b5f5f6137f661375d565b5f938452600201602052505060409020546001600160a01b031690565b60025f54036138645760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611b2f565b60025f55565b60325460ff1615611ce25760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401611b2f565b5f806138c862ed4e006001600160801b038516615a17565b90506138dc670de0b6b3a7640000826159ec565b90506001600160801b038111156108425760405162461bcd60e51b815260206004820152600e60248201526d0a6d8dee0ca40e8dede40d0d2ced60931b6044820152606401611b2f565b5f826001600160801b03165f036139465750670de0b6b3a7640000610842565b5f62ed4e00613963670de0b6b3a764000063ffffffff86166159ec565b61396d9190615a17565b90505f670de0b6b3a764000061398b81673782dace9d900000615a2a565b61399e906001600160801b0316846159ec565b6139a89190615a17565b6139ba90670de0b6b3a7640000615a49565b9050673782dace9d9000008111156139de57673782dace9d90000092505050610842565b670de0b6b3a764000081101561329757670de0b6b3a764000092505050610842565b5f838152606660209081526040808320815160808101835281546001600160801b038082168352600160801b90910416938101939093526001015463ffffffff808216928401839052600160201b9091048116606084015291929142161015613b38575f428360400151613a7491906159d0565b90505f62ed4e00613a93670de0b6b3a764000063ffffffff85166159ec565b613a9d9190615a17565b90505f670de0b6b3a7640000613abb81673782dace9d900000615a2a565b613ace906001600160801b0316846159ec565b613ad89190615a17565b613aea90670de0b6b3a7640000615a49565b9050673782dace9d900000811115613b0c57673782dace9d9000009350613b30565b670de0b6b3a7640000811015613b2c57670de0b6b3a76400009350613b30565b8093505b505050613b43565b50670de0b6b3a76400005b5f670de0b6b3a7640000613b636001600160801b038481169088166159ec565b613b6d9190615a17565b90505f670de0b6b3a7640000613b8f6001600160801b038781169089166159ec565b613b999190615a17565b905081811115613c1f575f613bae8383615a5c565b90506001600160801b03811115613bd857604051630fc12e3560e11b815260040160405180910390fd5b606e80548291905f90613bf59084906001600160801b0316615a6f565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555050613ca1565b80821115613ca1575f613c328284615a5c565b606e549091506001600160801b0316811115613c5d57606e80546001600160801b0319169055613c9f565b606e80548291905f90613c7a9084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b505b50505050505050565b613cb261441f565b82156113b1576113b1838383614720565b60015f55565b613cd1614819565b6109048282614862565b613ce3614819565b611ce261488f565b613cf3614819565b611ce2614897565b613d03614819565b611a6c816148ab565b613d1461386a565b6032805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613d493390565b604051612d8491906153e2565b6001600160a01b038216613d7f575f604051633250574960e11b8152600401611b2f91906153e2565b5f613d8b8383336148b3565b9050836001600160a01b0316816001600160a01b0316146111a9576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401611b2f565b5f8080613df262ed4e006001600160801b038816615a17565b9050613e06670de0b6b3a7640000826159ec565b90506001600160801b03811115613e505760405162461bcd60e51b815260206004820152600e60248201526d536c6f7065206f766572666c6f7760901b6044820152606401611b2f565b809250613e5d8386613926565b9150673782dace9d9000006001600160801b0383161115613e9157604051638f651fb760e01b815260040160405180910390fd5b836001600160801b0316826001600160801b03161015613ec457604051638199f5f360e01b815260040160405180910390fd5b50935093915050565b6040516001600160a01b03808516602483015283166044820152606481018290526111a99085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526149b2565b610904828260405180602001604052805f815250614a85565b6040516001600160a01b0383166024820152604481018290526113b190849063a9059cbb60e01b90606401613f01565b5f613f8d5f835f6148b3565b90506001600160a01b03811661090457604051637e27328960e01b815260048101839052602401611b2f565b33613fc2611ef6565b6001600160a01b031614611ce2573360405163118cdaa760e01b8152600401611b2f91906153e2565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f5f62093a808085604001516140719190615b82565b61407b9190615ba9565b90505f5b60ff81101561416c5761409562093a8083615a8e565b91508363ffffffff168263ffffffff1611156140e95760408501516140ba90856159d0565b63ffffffff1685602001516140cf9190615bcf565b855186906140de908390615bee565b600f0b90525061416c565b60408501516140f890836159d0565b63ffffffff16856020015161410d9190615bcf565b8551869061411c908390615bee565b600f90810b90915263ffffffff84165f908152606c602090815260409091205490880180519190920b9250614152908390615c1b565b600f0b90525063ffffffff8216604086015260010161407f565b505f845f0151600f0b121561417f575f84525b505090516001600160801b0316919050565b5f61419a61375d565b90506001600160a01b0383166141c55782604051630b61174360e31b8152600401611b2f91906153e2565b6001600160a01b038481165f818152600584016020908152604080832094881680845294825291829020805460ff191687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b61423f8484846113a6565b6111a93385858585614a98565b5f838152606660205260408120805490916001600160801b03909116906142738583615a6f565b600184015490915063ffffffff165f61428c42836159d0565b90505f614298846138b0565b90505f6142a58284613926565b90505f6142b18b611d98565b9050806001600160801b0316826001600160801b0316116142d257806142d4565b815b91506142ea6103e8670de0b6b3a7640000615c48565b6001600160801b03168a6001600160801b031611801561431b5750886001600160801b0316826001600160801b0316105b1561433957604051638199f5f360e01b815260040160405180910390fd5b61437e8b60405180604001604052808a600f0b81526020018863ffffffff1681525060405180604001604052808a600f0b81526020018963ffffffff16815250613caa565b6001600160801b03838116600160801b0290871617885560018801805463ffffffff4216600160201b0267ffffffff00000000199091161790556143c38b8b84613a00565b604080516001600160801b038c81168252888116602083015284168183015290518c9133917f1381e2f7d0d4b71a58d34dc3db2051dd52769766e65eabf380c9b4ea93f0890b9181900360600190a35050505050505050505050565b60695463ffffffff16614430615335565b63ffffffff8216156144a95760685f61444a6001856159d0565b63ffffffff908116825260208083019390935260409182015f2082516080810184528154600f81810b8352600160801b909104900b948101949094526001015480821692840192909252600160201b90910416606082015290506144d6565b50604080516080810182525f808252602082015263ffffffff428116928201929092524390911660608201525b60408101515f63ffffffff8083164290911611156145375760408301516145039063ffffffff1642615a5c565b60608401516145189063ffffffff1643615a5c565b61452a90670de0b6b3a76400006159ec565b6145349190615a17565b90505b61454383838387614bae565b9250614550846001615a8e565b6069805463ffffffff92831663ffffffff199091161790558481165f9081526068602090815260408083208751928801516001600160801b03908116600160801b0290841617815590870151600191909101805460608901518616600160201b026001600160401b0319909116929095169190911793909317909255600f9190910b12156111a95750505f905250565b6145e8614db7565b6032805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33613d49565b5f61462261375d565b9050818061463857506001600160a01b03831615155b156146f0575f61464785613781565b90506001600160a01b038416158015906146735750836001600160a01b0316816001600160a01b031614155b8015614686575061468481856136d6565b155b156146a6578360405163a9fbf51f60e01b8152600401611b2f91906153e2565b82156146ee5784866001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5f93845260040160205250506040902080546001600160a01b0319166001600160a01b0392909216919091179055565b614728615335565b614730615335565b61473a8483614e00565b506147458382614e00565b5061475a848484602001518460200151614f4f565b5f858152606a60205260408120546147799063ffffffff166001615a8e565b5f878152606a60209081526040808320805463ffffffff95861663ffffffff199091168117909155428516878301908152438616606089019081529b8552606b84528285209185529083529220855195909101516001600160801b03908116600160801b02951694909417845551600193909301805497518216600160201b026001600160401b0319909816939091169290921795909517905550505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611ce257604051631afcd79f60e31b815260040160405180910390fd5b61486a614819565b5f61487361375d565b9050806148808482615cba565b50600181016111a98382615cba565b613cc3614819565b61489f614819565b6032805460ff19169055565b61371b614819565b5f5f6148bd61375d565b90505f6148c9856137ec565b90506001600160a01b038416156148e5576148e581858761508a565b6001600160a01b03811615614921576149005f865f5f614619565b6001600160a01b0381165f908152600383016020526040902080545f190190555b6001600160a01b03861615614951576001600160a01b0386165f9081526003830160205260409020805460010190555b5f85815260028301602052604080822080546001600160a01b0319166001600160a01b038a811691821790925591518893918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a495945050505050565b5f614a06826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166150ee9092919063ffffffff16565b905080515f1480614a26575080806020019051810190614a269190615d74565b6113b15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401611b2f565b614a8f83836150fc565b6113b1335f8585855b6001600160a01b0383163b15614ba757604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290614ada908890889087908790600401615d8f565b6020604051808303815f875af1925050508015614b14575060408051601f3d908101601f19168201909252614b1191810190615dc1565b60015b614b72573d808015614b41576040519150601f19603f3d011682016040523d82523d5f602084013e614b46565b606091505b5080515f03614b6a5783604051633250574960e11b8152600401611b2f91906153e2565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14614ba55783604051633250574960e11b8152600401611b2f91906153e2565b505b5050505050565b614bb6615335565b5f62093a80614bc58187615b82565b614bcf9190615ba9565b9050425f5b60ff811015614dab57614bea62093a8084615a8e565b92508163ffffffff168363ffffffff161115614c4d57614c0a87836159d0565b63ffffffff168860200151614c1f9190615bcf565b88518990614c2e908390615bee565b600f0b90525063ffffffff80831660408a015243166060890152614dab565b614c5787846159d0565b63ffffffff168860200151614c6c9190615bcf565b88518990614c7b908390615bee565b600f90810b90915263ffffffff85165f908152606c6020908152604090912054908b0180519190920b9250614cb1908390615c1b565b600f0b90525063ffffffff831660408901819052670de0b6b3a764000090614cd990856159d0565b614cf29063ffffffff166001600160801b0389166159ec565b614cfc9190615a17565b886060015163ffffffff16614d119190615a49565b63ffffffff1660608901528760685f83614d2c896001615a8e565b614d369190615a8e565b63ffffffff908116825260208083019390935260409182015f208451938501516001600160801b03908116600160801b02941693909317835590830151600192830180546060909501518316600160201b026001600160401b0319909516919092161792909217909155929650869201614bd4565b50959695505050505050565b60325460ff16611ce25760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401611b2f565b5f4263ffffffff16836020015163ffffffff16111580614e2257508251600f0b155b15614e2e57505f610842565b5f428460200151614e3f91906159d0565b63ffffffff16905062ed4e008111614e575780614e5c565b62ed4e005b90505f62ed4e00614e7d670de0b6b3a7640000673782dace9d900000615a2a565b614e90906001600160801b0316846159ec565b614e9a9190615a17565b614eac90670de0b6b3a7640000615a49565b9050673782dace9d9000008111614ee057670de0b6b3a76400008110614ed25780614eea565b670de0b6b3a7640000614eea565b673782dace9d9000005b85519091506001600160801b0316670de0b6b3a7640000614f0b83836159ec565b614f159190615a17565b600f0b855262ed4e00614f30670de0b6b3a7640000836159ec565b614f3a9190615a17565b600f0b60208601525060019250505092915050565b4263ffffffff16846020015163ffffffff161115614ff05760208085015163ffffffff165f908152606c9091526040902054600f0b614f8e8382615c1b565b9050846020015163ffffffff16846020015163ffffffff1603614fb857614fb58282615bee565b90505b60208581015163ffffffff165f908152606c9091526040902080546001600160801b0319166001600160801b03929092169190911790555b4263ffffffff16836020015163ffffffff1611156111a957836020015163ffffffff16836020015163ffffffff1611156111a95760208084015163ffffffff165f908152606c9091526040902054600f0b61504b8282615bee565b60208086015163ffffffff165f908152606c9091526040902080546001600160801b039092166001600160801b03199092169190911790555050505050565b61509583838361515d565b6113b1576001600160a01b0383166150c357604051637e27328960e01b815260048101829052602401611b2f565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401611b2f565b606061329784845f856151c1565b6001600160a01b038216615125575f604051633250574960e11b8152600401611b2f91906153e2565b5f61513183835f6148b3565b90506001600160a01b038116156113b1575f6040516339e3563760e11b8152600401611b2f91906153e2565b5f6001600160a01b038316158015906132975750826001600160a01b0316846001600160a01b03161480615196575061519684846136d6565b806132975750826001600160a01b03166151af836137b8565b6001600160a01b031614949350505050565b6060824710156152225760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401611b2f565b5f5f866001600160a01b0316858760405161523d9190615ada565b5f6040518083038185875af1925050503d805f8114615277576040519150601f19603f3d011682016040523d82523d5f602084013e61527c565b606091505b509150915061528d87838387615298565b979650505050505050565b606083156153065782515f036152ff576001600160a01b0385163b6152ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611b2f565b5081613297565b613297838381511561531b5781518083602001fd5b8060405162461bcd60e51b8152600401611b2f91906153b9565b604080516080810182525f80825260208201819052918101829052606081019190915290565b6001600160e01b031981168114611a6c575f5ffd5b5f60208284031215615380575f5ffd5b8135611fa58161535b565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611fa5602083018461538b565b5f602082840312156153db575f5ffd5b5035919050565b6001600160a01b0391909116815260200190565b80356001600160a01b038116811461540c575f5ffd5b919050565b5f5f60408385031215615422575f5ffd5b61542b836153f6565b946020939093013593505050565b5f60208284031215615449575f5ffd5b611fa5826153f6565b602080825282518282018190525f918401906040840190835b8181101561548957835183526020938401939092019160010161546b565b509095945050505050565b803563ffffffff8116811461540c575f5ffd5b5f5f604083850312156154b8575f5ffd5b823591506154c860208401615494565b90509250929050565b80356001600160801b038116811461540c575f5ffd5b5f5f5f5f608085870312156154fa575f5ffd5b8435935061550a60208601615494565b92506040850135915061551f606086016154d1565b905092959194509250565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156155665761556661552a565b604052919050565b5f6001600160401b038211156155865761558661552a565b50601f01601f191660200190565b5f6155a66155a18461556e565b61553e565b90508281528383830111156155b9575f5ffd5b828260208301375f602084830101529392505050565b5f82601f8301126155de575f5ffd5b611fa583833560208501615594565b5f5f5f5f60808587031215615600575f5ffd5b615609856153f6565b9350615617602086016153f6565b925060408501356001600160401b03811115615631575f5ffd5b61563d878288016155cf565b92505060608501356001600160401b03811115615658575f5ffd5b615664878288016155cf565b91505092959194509250565b5f5f5f60608486031215615682575f5ffd5b61568b846153f6565b9250615699602085016153f6565b929592945050506040919091013590565b5f5f5f5f5f60a086880312156156be575f5ffd5b6156c7866153f6565b94506156d5602087016154d1565b93506156e360408701615494565b9250606086013591506156f8608087016154d1565b90509295509295909350565b5f60208284031215615714575f5ffd5b611fa582615494565b8015158114611a6c575f5ffd5b5f5f6040838503121561573b575f5ffd5b615744836153f6565b915060208301356157548161571d565b809150509250929050565b5f5f5f5f60808587031215615772575f5ffd5b61577b856153f6565b9350615789602086016153f6565b92506040850135915060608501356001600160401b038111156157aa575f5ffd5b8501601f810187136157ba575f5ffd5b61566487823560208401615594565b5f5f83601f8401126157d9575f5ffd5b5081356001600160401b038111156157ef575f5ffd5b6020830191508360208260051b8501011115615809575f5ffd5b9250929050565b5f5f5f60408486031215615822575f5ffd5b83356001600160401b03811115615837575f5ffd5b615843868287016157c9565b909790965060209590950135949350505050565b5f5f5f5f6080858703121561586a575f5ffd5b8435935061550a602086016154d1565b5f5f5f5f6040858703121561588d575f5ffd5b84356001600160401b038111156158a2575f5ffd5b6158ae878288016157c9565b90955093505060208501356001600160401b038111156158cc575f5ffd5b6158d8878288016157c9565b95989497509550505050565b5f5f604083850312156158f5575f5ffd5b6158fe836154d1565b91506154c860208401615494565b5f5f5f5f6080858703121561591f575f5ffd5b615928856154d1565b935061550a60208601615494565b5f5f60408385031215615947575f5ffd5b615950836153f6565b91506154c8602084016153f6565b600181811c9082168061597257607f821691505b6020821081036132fe57634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016159c9576159c96159a4565b5060010190565b63ffffffff8281168282160390811115610842576108426159a4565b8082028115828204841417610842576108426159a4565b634e487b7160e01b5f52601260045260245ffd5b5f82615a2557615a25615a03565b500490565b6001600160801b038281168282160390811115610842576108426159a4565b80820180821115610842576108426159a4565b81810381811115610842576108426159a4565b6001600160801b038181168382160190811115610842576108426159a4565b63ffffffff8181168382160190811115610842576108426159a4565b5f60208284031215615aba575f5ffd5b5051919050565b5f60208284031215615ad1575f5ffd5b611fa5826154d1565b5f82518060208501845e5f920191825250919050565b5f60208284031215615b00575f5ffd5b81516001600160401b03811115615b15575f5ffd5b8201601f81018413615b25575f5ffd5b8051615b336155a18261556e565b818152856020838501011115615b47575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f63ffffffff821680615b7957615b796159a4565b5f190192915050565b5f63ffffffff831680615b9757615b97615a03565b8063ffffffff84160491505092915050565b63ffffffff8181168382160290811690818114615bc857615bc86159a4565b5092915050565b5f82600f0b82600f0b0280600f0b9150808214615bc857615bc86159a4565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610842576108426159a4565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610842576108426159a4565b5f6001600160801b03831680615c6057615c60615a03565b6001600160801b03929092169190910492915050565b601f8211156113b157805f5260205f20601f840160051c81016020851015615c9b5750805b601f840160051c820191505b81811015614ba7575f8155600101615ca7565b81516001600160401b03811115615cd357615cd361552a565b615ce781615ce1845461595e565b84615c76565b6020601f821160018114615d19575f8315615d025750848201515b5f19600385901b1c1916600184901b178455614ba7565b5f84815260208120601f198516915b82811015615d485787850151825560209485019460019092019101615d28565b5084821015615d6557868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f60208284031215615d84575f5ffd5b8151611fa58161571d565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90611eec9083018461538b565b5f60208284031215615dd1575f5ffd5b8151611fa58161535b56fea264697066735822122067e3af8533ff98de13a52b43c98b05d159ba2d938981171b49d2e31bbb9f5c1464736f6c634300081b0033
Deployed Bytecode
0x608060405234801561000f575f5ffd5b50600436106102ad575f3560e01c806389f839c61161016c578063beb83109116100d5578063ddacc94a1161008f578063ddacc94a1461076b578063df0c78ef1461077e578063df21515714610791578063e58f5947146107a4578063e985e9c5146107c9578063f2fde38b146107dc578063f7b188a5146107ef575f5ffd5b8063beb831091461070f578063c5b1c7d014610722578063c71820101461072a578063c87b56dd1461073d578063d5c2589014610750578063d89dd26914610758575f5ffd5b806397612d4b1161012657806397612d4b146106645780639b7d02ad14610677578063a22cb465146106b4578063b88d4fde146106c7578063bbe33ea5146106da578063bcc00225146106ed575f5ffd5b806389f839c6146105525780638b25e8c1146105d55780638da5cb5b146105e85780638ff42490146105f0578063900cf0cf1461063757806395d89b411461065c575f5ffd5b80632a90752d11610219578063586c2600116101d3578063586c2600146104c95780635c975abb146104fe5780636352211e1461050957806370a082311461051c578063715018a61461052f57806375619ab5146105375780638456cb591461054a575f5ffd5b80632a90752d146104495780632e1a7d4d1461046a5780632e720f7d1461047d57806342842e0e146104905780635312ea8e146104a35780635594a045146104b6575f5ffd5b80631d237a491161026a5780631d237a49146103545780631f5ab022146103d95780632016a0d2146103ec57806320a194b8146103ff57806323b872dd14610411578063268dc19914610424575f5ffd5b806301ffc9a7146102b157806306fdde03146102d9578063081812fc146102ee578063095ea7b31461030e5780630f45cc811461032357806313de148b14610334575b5f5ffd5b6102c46102bf366004615370565b6107f7565b60405190151581526020015b60405180910390f35b6102e1610848565b6040516102d091906153b9565b6103016102fc3660046153cb565b6108e5565b6040516102d091906153e2565b61032161031c366004615411565b6108f9565b005b6064546001600160a01b0316610301565b610347610342366004615439565b610908565b6040516102d09190615452565b6103a66103623660046154a7565b606b60209081525f928352604080842090915290825290208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b60408051600f95860b81529390940b602084015263ffffffff9182169383019390935290911660608201526080016102d0565b6103216103e73660046154e7565b6109fc565b6103216103fa3660046155ed565b6111af565b606f54600160a01b900460ff166102c4565b61032161041f366004615670565b6113a6565b606e546001600160801b03165b6040516001600160801b0390911681526020016102d0565b61045c6104573660046156aa565b6113b6565b6040519081526020016102d0565b6103216104783660046153cb565b6117d4565b61032161048b366004615439565b611a6f565b61032161049e366004615670565b611ac0565b6103216104b13660046153cb565b611ada565b606d54610301906001600160a01b031681565b6104eb6104d7366004615704565b606c6020525f9081526040902054600f0b81565b604051600f9190910b81526020016102d0565b60325460ff166102c4565b6103016105173660046153cb565b611c72565b61045c61052a366004615439565b611c7c565b610321611cd1565b610321610545366004615439565b611ce4565b610321611d88565b61059e6105603660046153cb565b60666020525f9081526040902080546001909101546001600160801b0380831692600160801b9004169063ffffffff80821691600160201b90041684565b604080516001600160801b03958616815294909316602085015263ffffffff918216928401929092521660608201526080016102d0565b6104316105e33660046153cb565b611d98565b610301611ef6565b6103a66105fe366004615704565b60686020525f908152604090208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b6069546106479063ffffffff1681565b60405163ffffffff90911681526020016102d0565b6102e1611f24565b610431610672366004615704565b611f40565b6106a2610685366004615439565b6001600160a01b03165f9081526067602052604090205460ff1690565b60405160ff90911681526020016102d0565b6103216106c236600461572a565b611fac565b6103216106d536600461575f565b611fb7565b6103216106e8366004615810565b611fc3565b6106a26106fb366004615439565b60676020525f908152604090205460ff1681565b61032161071d366004615857565b612683565b610321612d24565b61032161073836600461587a565b612d8e565b6102e161074b3660046153cb565b61314c565b61045c61329f565b6104316107663660046158e4565b613304565b6104316107793660046154a7565b61339d565b61043161078c3660046158e4565b613654565b61045c61079f36600461590c565b61369e565b6106476107b23660046153cb565b606a6020525f908152604090205463ffffffff1681565b6102c46107d7366004615936565b6136d6565b6103216107ea366004615439565b613713565b61032161374d565b5f6001600160e01b031982166380ac58cd60e01b148061082757506001600160e01b03198216635b5e139f60e01b145b8061084257506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f61085361375d565b9050805f0180546108639061595e565b80601f016020809104026020016040519081016040528092919081815260200182805461088f9061595e565b80156108da5780601f106108b1576101008083540402835291602001916108da565b820191905f5260205f20905b8154815290600101906020018083116108bd57829003601f168201915b505050505091505090565b5f6108ef82613781565b50610842826137b8565b6109048282336137df565b5050565b6001600160a01b0381165f9081526067602052604090205460609060ff16806001600160401b0381111561093e5761093e61552a565b604051908082528060200260200182016040528015610967578160200160208202803683370190505b5091508060ff165f0361097a5750919050565b5f805b606554600160a01b900463ffffffff168110156109f457846001600160a01b03166109a7826137ec565b6001600160a01b0316036109ec57808483815181106109c8576109c8615990565b6020908102919091010152816109dd816159b8565b9250508260ff168210156109f4575b60010161097d565b505050919050565b610a04613813565b610a0c61386a565b8180421115610a2e57604051631ab7da6b60e01b815260040160405180910390fd5b5f85815260666020908152604091829020825160808101845281546001600160801b03808216808452600160801b909204169382019390935260019091015463ffffffff80821694830194909452600160201b9004909216606083015286919015801590610aab5750806040015163ffffffff164263ffffffff16105b15610e75575f428260400151610ac191906159d0565b90505f62ed4e00610ae0670de0b6b3a764000063ffffffff85166159ec565b610aea9190615a17565b90505f670de0b6b3a764000082610b0982673782dace9d900000615a2a565b6001600160801b0316610b1c91906159ec565b610b269190615a17565b610b3890670de0b6b3a7640000615a49565b905080673782dace9d9000006001600160801b0382161115610b5f5750673782dace9d9000005b670de0b6b3a76400006001600160801b0382161015610b835750670de0b6b3a76400005b84515f90670de0b6b3a764000090610ba89062ed4e00906001600160801b0316615a17565b610bb291906159ec565b90505f819050806001600160801b031687602001516001600160801b0316141580610bf4575062015180876060015163ffffffff1642610bf29190615a5c565b115b15610e6e5760208701515f906001600160801b031615610cd9575f62ed4e00610c2b670de0b6b3a764000063ffffffff8b166159ec565b610c359190615a17565b90505f670de0b6b3a764000082610c5482673782dace9d900000615a2a565b6001600160801b0316610c6791906159ec565b610c719190615a17565b610c8390670de0b6b3a7640000615a49565b9250829050673782dace9d9000006001600160801b0382161115610cad57673782dace9d90000092505b670de0b6b3a76400006001600160801b0384161015610cd257670de0b6b3a764000092505b5050610ce4565b50670de0b6b3a76400005b87515f90670de0b6b3a764000090610d08906001600160801b0385811691166159ec565b610d129190615a17565b89519091505f90670de0b6b3a764000090610d39906001600160801b0389811691166159ec565b610d439190615a17565b905081811115610da1575f610d588383615a5c565b606e805491925082915f90610d779084906001600160801b0316615a6f565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555050610e23565b80821115610e23575f610db48284615a5c565b606e549091506001600160801b0316811115610ddf57606e80546001600160801b0319169055610e21565b606e80548291905f90610dfc9084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b505b5050505f88815260666020526040902080546001600160801b03808416600160801b029116178155600101805463ffffffff4216600160201b0267ffffffff00000000199091161790555b5050505050505b33610e7f88611c72565b6001600160a01b031614610ea6576040516359dc379f60e01b815260040160405180910390fd5b5f878152606660209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b900490911660608201529103610f2157604051632254ea3d60e11b815260040160405180910390fd5b5f4263ffffffff16826040015163ffffffff161015610f4b57610f448842615a8e565b9050610f5e565b878260400151610f5b9190615a8e565b90505b5f610f6942836159d0565b905062ed4e0063ffffffff82161115610f9557604051637616640160e01b815260040160405180910390fd5b5f610fa2845f01516138b0565b90505f610faf8284613926565b9050886001600160801b0316816001600160801b03161015610fe457604051638199f5f360e01b815260040160405180910390fd5b610ff28c865f015183613a00565b6110418c6040518060400160405280885f0151600f0b8152602001886040015163ffffffff168152506040518060400160405280895f0151600f0b81526020018863ffffffff16815250613caa565b6040518060800160405280865f01516001600160801b03168152602001836001600160801b031681526020018563ffffffff1681526020014263ffffffff1681525060665f8e81526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055509050508b336001600160a01b03167f3032be442129e161b4ae1cdee94871a69de2c16ee2007f31fc209a715673455c868460405161119092919063ffffffff9290921682526001600160801b0316602082015260400190565b60405180910390a350505050505050506111a960015f55565b50505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f811580156111f35750825b90505f826001600160401b0316600114801561120e5750303b155b90508115801561121c575080155b1561123a5760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b0319166001178555831561126357845460ff60401b1916600160401b1785555b6001600160a01b038916158061128057506001600160a01b038816155b1561129e5760405163d92e233d60e01b815260040160405180910390fd5b6112a88787613cc9565b6112b0613cdb565b6112b8613ceb565b6112c133613cfb565b6112c9613d0c565b606480546001600160a01b03808c166001600160a01b031992831617909255606f8054928b16929091169190911790555f805260686020527fad6f8124f6081c2622ab3a16acd47af73d52fe87b755c3f897263c58ba3fdbd880544263ffffffff90811663ffffffff194392909216600160201b02919091166001600160401b031990921691909117179055831561139b57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b6113b1838383613d56565b505050565b5f6113bf613813565b6113c761386a565b82804211156113e957604051631ab7da6b60e01b815260040160405180910390fd5b856001600160801b03165f036114125760405163162908e360e11b815260040160405180910390fd5b63ffffffff8516158061142d575062ed4e0063ffffffff8616115b1561144b57604051637616640160e01b815260040160405180910390fd5b6001600160a01b0387166114725760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0387165f90815260676020526040902054606460ff909116106114af5760405163133cbc4f60e01b815260040160405180910390fd5b5f6114ba8642615a8e565b90505f5f6114c9898988613dd9565b915091505f60405180604001604052808b600f0b81526020018563ffffffff1681525090506115165f60405180604001604052805f600f0b81526020015f63ffffffff1681525083613caa565b6064546040516370a0823160e01b81525f916001600160a01b0316906370a08231906115469030906004016153e2565b602060405180830381865afa158015611561573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115859190615aaa565b6064549091506115a9906001600160a01b031633306001600160801b038f16613ecd565b6115bc6001600160801b038c1682615a49565b6064546040516370a0823160e01b81526001600160a01b03909116906370a08231906115ec9030906004016153e2565b602060405180830381865afa158015611607573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061162b9190615aaa565b14611649576040516312171d8360e31b815260040160405180910390fd5b60658054600163ffffffff600160a01b80840482168381019092160263ffffffff60a01b19909316929092179092556001600160a01b038e165f908152606760205260409020805460ff80821690940190931660ff199093169290921790915596506116b58c88613f38565b604080516080810182526001600160801b03808e168252868116602080840191825263ffffffff808b16858701908152428216606087019081525f8f8152606690945296909220945192518416600160801b0292909316919091178355516001909201805493518216600160201b026001600160401b03199094169290911691909117919091179055611749878c85613a00565b604080518082019091525f808252602082015261176890889084613caa565b604080516001600160801b038d16815263ffffffff8716602082015288916001600160a01b038f16917fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f8597828934954910160405180910390a35050505050506117cb60015f55565b95945050505050565b6117dc613813565b6117e461386a565b5f6117ee826137ec565b90506001600160a01b03811661181657604051626f708760e21b815260040160405180910390fd5b6001600160a01b038116331461183f576040516359dc379f60e01b815260040160405180910390fd5b5f828152606660209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b9004909116606082015291036118ba57604051632254ea3d60e11b815260040160405180910390fd5b806040015163ffffffff164263ffffffff1610156118eb5760405163342ad40160e11b815260040160405180910390fd5b8051606e546001600160801b03908116908216111561191957606e80546001600160801b031916905561195b565b606e80548291905f906119369084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b5f84815260666020908152604080832083815560010180546001600160401b031916905580518082018252600f85900b81528582015163ffffffff1681840152815180830190925283825291810192909252906119bb9086908390613caa565b5f858152606a60205260409020805463ffffffff191690556064546119f3906001600160a01b0316336001600160801b038516613f51565b6119fc85613f81565b335f81815260676020908152604091829020805460ff19811660ff9182165f190190911617905590516001600160801b03851681528792917f8903a5b5d08a841e7f68438387f1da20c84dea756379ed37e633ff3854b99b84910160405180910390a350505050611a6c60015f55565b50565b611a77613fb9565b6001600160a01b038116611a9e5760405163d92e233d60e01b815260040160405180910390fd5b606d80546001600160a01b0319166001600160a01b0392909216919091179055565b6113b183838360405180602001604052805f815250611fb7565b611ae2613813565b606f54600160a01b900460ff16611b385760405162461bcd60e51b81526020600482015260156024820152744e6f7420696e20656d657267656e6379206d6f646560581b60448201526064015b60405180910390fd5b33611b4282611c72565b6001600160a01b031614611b69576040516359dc379f60e01b815260040160405180910390fd5b5f818152606660208181526040808420815160808101835281546001600160801b03808216808452600160801b909204168286015260018301805463ffffffff80821696850196909652600160201b81049095166060840152888852959094529490556001600160401b031916909155611be283613f81565b335f818152606760205260409020805460ff19811660ff9182165f1901909116179055606454611c27916001600160a01b03909116906001600160801b038416613f51565b6040516001600160801b0382168152839033907f4f27eb511b2a4633cfb633ac1c4a99b4c298ca6488b29ec26f3504a5927f67289060200160405180910390a35050611a6c60015f55565b5f61084282613781565b5f5f611c8661375d565b90506001600160a01b038316611cb1575f6040516322718ad960e21b8152600401611b2f91906153e2565b6001600160a01b039092165f908152600390920160205250604090205490565b611cd9613fb9565b611ce25f613feb565b565b611cec613fb9565b6001600160a01b038116611d135760405163d92e233d60e01b815260040160405180910390fd5b6065546001600160a01b031615611d665760405162461bcd60e51b8152602060048201526017602482015276111a5cdd1c9a589d5d1bdc88185b1c9958591e481cd95d604a1b6044820152606401611b2f565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b611d90613fb9565b611ce2613d0c565b5f818152606660209081526040808320815160808101835281546001600160801b038082168352600160801b90910416938101939093526001015463ffffffff808216928401839052600160201b90910481166060840152421610611e075750670de0b6b3a764000092915050565b5f428260400151611e1891906159d0565b90505f62ed4e00611e37670de0b6b3a764000063ffffffff85166159ec565b611e419190615a17565b90505f670de0b6b3a764000082611e6082673782dace9d900000615a2a565b6001600160801b0316611e7391906159ec565b611e7d9190615a17565b611e8f90670de0b6b3a7640000615a49565b905080673782dace9d9000006001600160801b0382161115611ebf5750673782dace9d9000009695505050505050565b670de0b6b3a76400006001600160801b0382161015611eec5750670de0b6b3a76400009695505050505050565b9695505050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b60605f611f2f61375d565b90508060010180546108639061595e565b60695463ffffffff9081165f90815260686020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001015480851691830191909152600160201b9004909216606083015290611fa5818461405b565b9392505050565b610904338383614191565b6111a984848484614234565b611fcb613813565b611fd361386a565b8080421115611ff557604051631ab7da6b60e01b815260040160405180910390fd5b60028310156120175760405163162908e360e11b815260040160405180910390fd5b5f8042815b86811015612221573361204689898481811061203a5761203a615990565b90506020020135611c72565b6001600160a01b03161461206d576040516359dc379f60e01b815260040160405180910390fd5b5f60665f8a8a8581811061208357612083615990565b602090810292909201358352508181019290925260409081015f908120825160808101845281546001600160801b03808216808452600160801b909204169582019590955260019091015463ffffffff80821694830194909452600160201b900490921660608301529092500361210d57604051632254ea3d60e11b815260040160405180910390fd5b80516121199086615a6f565b94508263ffffffff16816040015163ffffffff1611801561214957508363ffffffff16816040015163ffffffff16115b1561215657806040015193505b5f6121788a8a8581811061216c5761216c615990565b90506020020135611d98565b82519091505f90670de0b6b3a76400009061219f906001600160801b0380861691166159ec565b6121a99190615a17565b606e549091506001600160801b03168111156121d457606e80546001600160801b0319169055612216565b606e80548291905f906121f19084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b50505060010161201c565b508063ffffffff168263ffffffff1611612245576122428162093a80615a8e565b91505b5f5b86811015612391575f60665f8a8a8581811061226557612265615990565b602090810292909201358352508181019290925260409081015f20815160808101835281546001600160801b038082168352600160801b909104168185015260019091015463ffffffff808216838501908152600160201b9092048116606084015283518085019094528251600f0b8452905116928201929092529091506123238a8a858181106122f8576122f8615990565b905060200201358260405180604001604052805f600f0b81526020015f63ffffffff16815250613caa565b60665f8b8b8681811061233857612338615990565b602090810292909201358352508101919091526040015f90812090815560010180546001600160401b03191690556123878a8a8581811061237b5761237b615990565b90506020020135613f81565b5050600101612247565b50606554600160a01b900463ffffffff165b5f6123b363ffffffff83166137ec565b6001600160a01b0316146123c9576001016123a3565b6123d4816001615a8e565b6065805463ffffffff60a01b1916600160a01b63ffffffff938416021790556124009033908316613f38565b5f61240b83856159d0565b905062ed4e0063ffffffff8216111561243757604051637616640160e01b815260040160405180910390fd5b5f62ed4e00612457670de0b6b3a76400006001600160801b0389166159ec565b6124619190615a17565b604080516080810182526001600160801b03808a168252808416602080840191825263ffffffff808c168587018181528c8316606088019081528c84165f818152606687528a8120995197518916600160801b029790981696909617885590516001909701805491518416600160201b026001600160401b0319909216979093169690961795909517905584518086018652600f8d900b8152808201949094528451808601909552828552840191909152929350916125209183613caa565b5f61252b8385613926565b90505f670de0b6b3a764000061254d6001600160801b03808516908c166159ec565b6125579190615a17565b606e805491925082915f906125769084906001600160801b0316615a6f565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508c8c905060675f336001600160a01b03166001600160a01b031681526020019081526020015f205f9054906101000a900460ff160360010160675f336001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548160ff021916908360ff1602179055508563ffffffff16336001600160a01b03167fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f85978289349548b8b6040516126689291906001600160801b0392909216825263ffffffff16602082015260400190565b60405180910390a3505050505050505050506113b160015f55565b61268b613813565b61269361386a565b81804211156126b557604051631ab7da6b60e01b815260040160405180910390fd5b5f85815260666020908152604091829020825160808101845281546001600160801b03808216808452600160801b909204169382019390935260019091015463ffffffff80821694830194909452600160201b90049092166060830152869190158015906127325750806040015163ffffffff164263ffffffff16105b15612afc575f42826040015161274891906159d0565b90505f62ed4e00612767670de0b6b3a764000063ffffffff85166159ec565b6127719190615a17565b90505f670de0b6b3a76400008261279082673782dace9d900000615a2a565b6001600160801b03166127a391906159ec565b6127ad9190615a17565b6127bf90670de0b6b3a7640000615a49565b905080673782dace9d9000006001600160801b03821611156127e65750673782dace9d9000005b670de0b6b3a76400006001600160801b038216101561280a5750670de0b6b3a76400005b84515f90670de0b6b3a76400009061282f9062ed4e00906001600160801b0316615a17565b61283991906159ec565b90505f819050806001600160801b031687602001516001600160801b031614158061287b575062015180876060015163ffffffff16426128799190615a5c565b115b15612af55760208701515f906001600160801b031615612960575f62ed4e006128b2670de0b6b3a764000063ffffffff8b166159ec565b6128bc9190615a17565b90505f670de0b6b3a7640000826128db82673782dace9d900000615a2a565b6001600160801b03166128ee91906159ec565b6128f89190615a17565b61290a90670de0b6b3a7640000615a49565b9250829050673782dace9d9000006001600160801b038216111561293457673782dace9d90000092505b670de0b6b3a76400006001600160801b038416101561295957670de0b6b3a764000092505b505061296b565b50670de0b6b3a76400005b87515f90670de0b6b3a76400009061298f906001600160801b0385811691166159ec565b6129999190615a17565b89519091505f90670de0b6b3a7640000906129c0906001600160801b0389811691166159ec565b6129ca9190615a17565b905081811115612a28575f6129df8383615a5c565b606e805491925082915f906129fe9084906001600160801b0316615a6f565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555050612aaa565b80821115612aaa575f612a3b8284615a5c565b606e549091506001600160801b0316811115612a6657606e80546001600160801b0319169055612aa8565b606e80548291905f90612a839084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b505b5050505f88815260666020526040902080546001600160801b03808416600160801b029116178155600101805463ffffffff4216600160201b0267ffffffff00000000199091161790555b5050505050505b32612b0688611c72565b6001600160a01b031614612b455733612b1e88611c72565b6001600160a01b031614612b45576040516359dc379f60e01b815260040160405180910390fd5b856001600160801b03165f03612b6e5760405163162908e360e11b815260040160405180910390fd5b5f878152606660205260408120805490916001600160801b039091169003612ba957604051632254ea3d60e11b815260040160405180910390fd5b600181015463ffffffff9081164290911610612bd8576040516307b7d7dd60e51b815260040160405180910390fd5b6064546040516370a0823160e01b81525f916001600160a01b0316906370a0823190612c089030906004016153e2565b602060405180830381865afa158015612c23573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c479190615aaa565b606454909150612c6b906001600160a01b031633306001600160801b038c16613ecd565b612c7e6001600160801b03891682615a49565b6064546040516370a0823160e01b81526001600160a01b03909116906370a0823190612cae9030906004016153e2565b602060405180830381865afa158015612cc9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ced9190615aaa565b14612d0b576040516312171d8360e31b815260040160405180910390fd5b612d1689898861424c565b50505050506111a960015f55565b612d2c613fb9565b606f805460ff60a01b1916600160a01b179055612d47613d0c565b606f546040517fc0a1c7e9f05b4d536e1ff8606bae9b847cdb43ef4a9b2d7a503a88cee08dccdb91612d84916001600160a01b03909116906153e2565b60405180910390a1565b612d96613fb9565b828114612de05760405162461bcd60e51b8152602060048201526018602482015277082e4e4c2f240d8cadccee8d0e640daeae6e840dac2e8c6d60431b6044820152606401611b2f565b5f5b83811015613143575f858583818110612dfd57612dfd615990565b9050602002013590505f6001600160a01b0316612e19826137ec565b6001600160a01b031603612e305750600101612de2565b5f81815260666020908152604091829020825160808101845281546001600160801b03808216808452600160801b909204169382019390935260019091015463ffffffff80821694830194909452600160201b9004909216606083015215613139575f858585818110612ea557612ea5615990565b9050602002016020810190612eba9190615ac1565b90506001600160801b03811615613137575f612ed584611d98565b83519091505f90670de0b6b3a764000090612efc906001600160801b0380861691166159ec565b612f069190615a17565b90505f670de0b6b3a76400006001600160801b0316836001600160801b031685875f0151612f349190615a2a565b6001600160801b0316612f4791906159ec565b612f519190615a17565b606e549091506001600160801b0316821115612f7c57606e80546001600160801b0319169055612fbe565b606e80548391905f90612f999084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b606e80548291905f90612fdb9084906001600160801b0316615a6f565b82546101009290920a6001600160801b038181021990931691831602179091555f8881526066602052604081208054889450909261301b91859116615a2a565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555062ed4e0063ffffffff16670de0b6b3a76400006001600160801b031685875f015161306a9190615a2a565b6001600160801b031661307d91906159ec565b6130879190615a17565b5f8781526066602090815260409182902080546001600160801b03948516600160801b02941693909317909255805180820182528751600f0b81528782015163ffffffff16928101929092528051808201909152865161310d928992909181906130f2908a90615a2a565b600f0b8152602001896040015163ffffffff16815250613caa565b606554606454613133916001600160a01b0391821691166001600160801b038716613f51565b5050505b505b5050600101612de2565b506111a961441f565b60605f613158836137ec565b6001600160a01b03160361317e57604051626f708760e21b815260040160405180910390fd5b606d546001600160a01b03166131a7576040516338a69c8d60e21b815260040160405180910390fd5b606d54604051602481018490525f9182916001600160a01b039091169060440160408051601f198184030181529181526020820180516001600160e01b031663c87b56dd60e01b179052516131fc9190615ada565b5f60405180830381855afa9150503d805f8114613234576040519150601f19603f3d011682016040523d82523d5f602084013e613239565b606091505b5091509150816132835760405162461bcd60e51b8152602060048201526015602482015274105c9d081c1c9bde1e4818d85b1b0819985a5b1959605a1b6044820152606401611b2f565b808060200190518101906132979190615af0565b949350505050565b5f80805b606554600160a01b900463ffffffff168110156132fe575f6132c4826137ec565b6001600160a01b0316146132f6575f818152606660205260409020546132f3906001600160801b031683615a49565b91505b6001016132a3565b50919050565b5f63ffffffff82161580613320575062ed4e0063ffffffff8316115b1561333e57604051637616640160e01b815260040160405180910390fd5b826001600160801b03165f036133675760405163162908e360e11b815260040160405180910390fd5b5f670de0b6b3a764000061338762ed4e006001600160801b038716615a17565b61339191906159ec565b90506132978184613926565b5f828152606660209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b90049091166060820152908203613409575f915050610842565b806040015163ffffffff168363ffffffff161061342857519050610842565b806060015163ffffffff168363ffffffff161015613449575f915050610842565b60408101515f9062ed4e0090670de0b6b3a76400009061346a9087906159d0565b63ffffffff1661347a91906159ec565b6134849190615a17565b90505f670de0b6b3a76400006134a281673782dace9d900000615a2a565b6134b5906001600160801b0316846159ec565b6134bf9190615a17565b6134d190670de0b6b3a7640000615a49565b9050673782dace9d900000811161350557670de0b6b3a764000081106134f7578061350f565b670de0b6b3a764000061350f565b673782dace9d9000005b83519091505f90670de0b6b3a7640000906135349084906001600160801b03166159ec565b61353e9190615a17565b90506001600160801b03811115613562576001600160801b03945050505050610842565b5f878152606a602052604090205463ffffffff16805b60018163ffffffff1610613647575f898152606b6020908152604080832063ffffffff80861685529083529281902081516080810183528154600f81810b8352600160801b909104900b9381019390935260010154808416918301829052600160201b90048316606083015290918a1610613634578051600f0b158015613608575086516001600160801b031615155b1561361c5783975050505050505050610842565b516001600160801b0316965061084295505050505050565b508061363f81615b64565b915050613578565b5090979650505050505050565b606d545f90819063ffffffff600160a01b9091048116908416116136785782613692565b606d5461369290600160a01b900463ffffffff16846159d0565b90506132978482613304565b5f6136a761386a565b82804211156136c957604051631ab7da6b60e01b815260040160405180910390fd5b611eec33878787876113b6565b5f5f6136e061375d565b6001600160a01b039485165f90815260059190910160209081526040808320959096168252939093525050205460ff1690565b61371b613fb9565b6001600160a01b038116613744575f604051631e4fbdf760e01b8152600401611b2f91906153e2565b611a6c81613feb565b613755613fb9565b611ce26145e0565b7f80bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab007930090565b5f5f61378c836137ec565b90506001600160a01b03811661084257604051637e27328960e01b815260048101849052602401611b2f565b5f5f6137c261375d565b5f938452600401602052505060409020546001600160a01b031690565b6113b18383836001614619565b5f5f6137f661375d565b5f938452600201602052505060409020546001600160a01b031690565b60025f54036138645760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611b2f565b60025f55565b60325460ff1615611ce25760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401611b2f565b5f806138c862ed4e006001600160801b038516615a17565b90506138dc670de0b6b3a7640000826159ec565b90506001600160801b038111156108425760405162461bcd60e51b815260206004820152600e60248201526d0a6d8dee0ca40e8dede40d0d2ced60931b6044820152606401611b2f565b5f826001600160801b03165f036139465750670de0b6b3a7640000610842565b5f62ed4e00613963670de0b6b3a764000063ffffffff86166159ec565b61396d9190615a17565b90505f670de0b6b3a764000061398b81673782dace9d900000615a2a565b61399e906001600160801b0316846159ec565b6139a89190615a17565b6139ba90670de0b6b3a7640000615a49565b9050673782dace9d9000008111156139de57673782dace9d90000092505050610842565b670de0b6b3a764000081101561329757670de0b6b3a764000092505050610842565b5f838152606660209081526040808320815160808101835281546001600160801b038082168352600160801b90910416938101939093526001015463ffffffff808216928401839052600160201b9091048116606084015291929142161015613b38575f428360400151613a7491906159d0565b90505f62ed4e00613a93670de0b6b3a764000063ffffffff85166159ec565b613a9d9190615a17565b90505f670de0b6b3a7640000613abb81673782dace9d900000615a2a565b613ace906001600160801b0316846159ec565b613ad89190615a17565b613aea90670de0b6b3a7640000615a49565b9050673782dace9d900000811115613b0c57673782dace9d9000009350613b30565b670de0b6b3a7640000811015613b2c57670de0b6b3a76400009350613b30565b8093505b505050613b43565b50670de0b6b3a76400005b5f670de0b6b3a7640000613b636001600160801b038481169088166159ec565b613b6d9190615a17565b90505f670de0b6b3a7640000613b8f6001600160801b038781169089166159ec565b613b999190615a17565b905081811115613c1f575f613bae8383615a5c565b90506001600160801b03811115613bd857604051630fc12e3560e11b815260040160405180910390fd5b606e80548291905f90613bf59084906001600160801b0316615a6f565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555050613ca1565b80821115613ca1575f613c328284615a5c565b606e549091506001600160801b0316811115613c5d57606e80546001600160801b0319169055613c9f565b606e80548291905f90613c7a9084906001600160801b0316615a2a565b92506101000a8154816001600160801b0302191690836001600160801b031602179055505b505b50505050505050565b613cb261441f565b82156113b1576113b1838383614720565b60015f55565b613cd1614819565b6109048282614862565b613ce3614819565b611ce261488f565b613cf3614819565b611ce2614897565b613d03614819565b611a6c816148ab565b613d1461386a565b6032805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613d493390565b604051612d8491906153e2565b6001600160a01b038216613d7f575f604051633250574960e11b8152600401611b2f91906153e2565b5f613d8b8383336148b3565b9050836001600160a01b0316816001600160a01b0316146111a9576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401611b2f565b5f8080613df262ed4e006001600160801b038816615a17565b9050613e06670de0b6b3a7640000826159ec565b90506001600160801b03811115613e505760405162461bcd60e51b815260206004820152600e60248201526d536c6f7065206f766572666c6f7760901b6044820152606401611b2f565b809250613e5d8386613926565b9150673782dace9d9000006001600160801b0383161115613e9157604051638f651fb760e01b815260040160405180910390fd5b836001600160801b0316826001600160801b03161015613ec457604051638199f5f360e01b815260040160405180910390fd5b50935093915050565b6040516001600160a01b03808516602483015283166044820152606481018290526111a99085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526149b2565b610904828260405180602001604052805f815250614a85565b6040516001600160a01b0383166024820152604481018290526113b190849063a9059cbb60e01b90606401613f01565b5f613f8d5f835f6148b3565b90506001600160a01b03811661090457604051637e27328960e01b815260048101839052602401611b2f565b33613fc2611ef6565b6001600160a01b031614611ce2573360405163118cdaa760e01b8152600401611b2f91906153e2565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f5f62093a808085604001516140719190615b82565b61407b9190615ba9565b90505f5b60ff81101561416c5761409562093a8083615a8e565b91508363ffffffff168263ffffffff1611156140e95760408501516140ba90856159d0565b63ffffffff1685602001516140cf9190615bcf565b855186906140de908390615bee565b600f0b90525061416c565b60408501516140f890836159d0565b63ffffffff16856020015161410d9190615bcf565b8551869061411c908390615bee565b600f90810b90915263ffffffff84165f908152606c602090815260409091205490880180519190920b9250614152908390615c1b565b600f0b90525063ffffffff8216604086015260010161407f565b505f845f0151600f0b121561417f575f84525b505090516001600160801b0316919050565b5f61419a61375d565b90506001600160a01b0383166141c55782604051630b61174360e31b8152600401611b2f91906153e2565b6001600160a01b038481165f818152600584016020908152604080832094881680845294825291829020805460ff191687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b61423f8484846113a6565b6111a93385858585614a98565b5f838152606660205260408120805490916001600160801b03909116906142738583615a6f565b600184015490915063ffffffff165f61428c42836159d0565b90505f614298846138b0565b90505f6142a58284613926565b90505f6142b18b611d98565b9050806001600160801b0316826001600160801b0316116142d257806142d4565b815b91506142ea6103e8670de0b6b3a7640000615c48565b6001600160801b03168a6001600160801b031611801561431b5750886001600160801b0316826001600160801b0316105b1561433957604051638199f5f360e01b815260040160405180910390fd5b61437e8b60405180604001604052808a600f0b81526020018863ffffffff1681525060405180604001604052808a600f0b81526020018963ffffffff16815250613caa565b6001600160801b03838116600160801b0290871617885560018801805463ffffffff4216600160201b0267ffffffff00000000199091161790556143c38b8b84613a00565b604080516001600160801b038c81168252888116602083015284168183015290518c9133917f1381e2f7d0d4b71a58d34dc3db2051dd52769766e65eabf380c9b4ea93f0890b9181900360600190a35050505050505050505050565b60695463ffffffff16614430615335565b63ffffffff8216156144a95760685f61444a6001856159d0565b63ffffffff908116825260208083019390935260409182015f2082516080810184528154600f81810b8352600160801b909104900b948101949094526001015480821692840192909252600160201b90910416606082015290506144d6565b50604080516080810182525f808252602082015263ffffffff428116928201929092524390911660608201525b60408101515f63ffffffff8083164290911611156145375760408301516145039063ffffffff1642615a5c565b60608401516145189063ffffffff1643615a5c565b61452a90670de0b6b3a76400006159ec565b6145349190615a17565b90505b61454383838387614bae565b9250614550846001615a8e565b6069805463ffffffff92831663ffffffff199091161790558481165f9081526068602090815260408083208751928801516001600160801b03908116600160801b0290841617815590870151600191909101805460608901518616600160201b026001600160401b0319909116929095169190911793909317909255600f9190910b12156111a95750505f905250565b6145e8614db7565b6032805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33613d49565b5f61462261375d565b9050818061463857506001600160a01b03831615155b156146f0575f61464785613781565b90506001600160a01b038416158015906146735750836001600160a01b0316816001600160a01b031614155b8015614686575061468481856136d6565b155b156146a6578360405163a9fbf51f60e01b8152600401611b2f91906153e2565b82156146ee5784866001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5f93845260040160205250506040902080546001600160a01b0319166001600160a01b0392909216919091179055565b614728615335565b614730615335565b61473a8483614e00565b506147458382614e00565b5061475a848484602001518460200151614f4f565b5f858152606a60205260408120546147799063ffffffff166001615a8e565b5f878152606a60209081526040808320805463ffffffff95861663ffffffff199091168117909155428516878301908152438616606089019081529b8552606b84528285209185529083529220855195909101516001600160801b03908116600160801b02951694909417845551600193909301805497518216600160201b026001600160401b0319909816939091169290921795909517905550505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611ce257604051631afcd79f60e31b815260040160405180910390fd5b61486a614819565b5f61487361375d565b9050806148808482615cba565b50600181016111a98382615cba565b613cc3614819565b61489f614819565b6032805460ff19169055565b61371b614819565b5f5f6148bd61375d565b90505f6148c9856137ec565b90506001600160a01b038416156148e5576148e581858761508a565b6001600160a01b03811615614921576149005f865f5f614619565b6001600160a01b0381165f908152600383016020526040902080545f190190555b6001600160a01b03861615614951576001600160a01b0386165f9081526003830160205260409020805460010190555b5f85815260028301602052604080822080546001600160a01b0319166001600160a01b038a811691821790925591518893918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a495945050505050565b5f614a06826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166150ee9092919063ffffffff16565b905080515f1480614a26575080806020019051810190614a269190615d74565b6113b15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401611b2f565b614a8f83836150fc565b6113b1335f8585855b6001600160a01b0383163b15614ba757604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290614ada908890889087908790600401615d8f565b6020604051808303815f875af1925050508015614b14575060408051601f3d908101601f19168201909252614b1191810190615dc1565b60015b614b72573d808015614b41576040519150601f19603f3d011682016040523d82523d5f602084013e614b46565b606091505b5080515f03614b6a5783604051633250574960e11b8152600401611b2f91906153e2565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14614ba55783604051633250574960e11b8152600401611b2f91906153e2565b505b5050505050565b614bb6615335565b5f62093a80614bc58187615b82565b614bcf9190615ba9565b9050425f5b60ff811015614dab57614bea62093a8084615a8e565b92508163ffffffff168363ffffffff161115614c4d57614c0a87836159d0565b63ffffffff168860200151614c1f9190615bcf565b88518990614c2e908390615bee565b600f0b90525063ffffffff80831660408a015243166060890152614dab565b614c5787846159d0565b63ffffffff168860200151614c6c9190615bcf565b88518990614c7b908390615bee565b600f90810b90915263ffffffff85165f908152606c6020908152604090912054908b0180519190920b9250614cb1908390615c1b565b600f0b90525063ffffffff831660408901819052670de0b6b3a764000090614cd990856159d0565b614cf29063ffffffff166001600160801b0389166159ec565b614cfc9190615a17565b886060015163ffffffff16614d119190615a49565b63ffffffff1660608901528760685f83614d2c896001615a8e565b614d369190615a8e565b63ffffffff908116825260208083019390935260409182015f208451938501516001600160801b03908116600160801b02941693909317835590830151600192830180546060909501518316600160201b026001600160401b0319909516919092161792909217909155929650869201614bd4565b50959695505050505050565b60325460ff16611ce25760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401611b2f565b5f4263ffffffff16836020015163ffffffff16111580614e2257508251600f0b155b15614e2e57505f610842565b5f428460200151614e3f91906159d0565b63ffffffff16905062ed4e008111614e575780614e5c565b62ed4e005b90505f62ed4e00614e7d670de0b6b3a7640000673782dace9d900000615a2a565b614e90906001600160801b0316846159ec565b614e9a9190615a17565b614eac90670de0b6b3a7640000615a49565b9050673782dace9d9000008111614ee057670de0b6b3a76400008110614ed25780614eea565b670de0b6b3a7640000614eea565b673782dace9d9000005b85519091506001600160801b0316670de0b6b3a7640000614f0b83836159ec565b614f159190615a17565b600f0b855262ed4e00614f30670de0b6b3a7640000836159ec565b614f3a9190615a17565b600f0b60208601525060019250505092915050565b4263ffffffff16846020015163ffffffff161115614ff05760208085015163ffffffff165f908152606c9091526040902054600f0b614f8e8382615c1b565b9050846020015163ffffffff16846020015163ffffffff1603614fb857614fb58282615bee565b90505b60208581015163ffffffff165f908152606c9091526040902080546001600160801b0319166001600160801b03929092169190911790555b4263ffffffff16836020015163ffffffff1611156111a957836020015163ffffffff16836020015163ffffffff1611156111a95760208084015163ffffffff165f908152606c9091526040902054600f0b61504b8282615bee565b60208086015163ffffffff165f908152606c9091526040902080546001600160801b039092166001600160801b03199092169190911790555050505050565b61509583838361515d565b6113b1576001600160a01b0383166150c357604051637e27328960e01b815260048101829052602401611b2f565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401611b2f565b606061329784845f856151c1565b6001600160a01b038216615125575f604051633250574960e11b8152600401611b2f91906153e2565b5f61513183835f6148b3565b90506001600160a01b038116156113b1575f6040516339e3563760e11b8152600401611b2f91906153e2565b5f6001600160a01b038316158015906132975750826001600160a01b0316846001600160a01b03161480615196575061519684846136d6565b806132975750826001600160a01b03166151af836137b8565b6001600160a01b031614949350505050565b6060824710156152225760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401611b2f565b5f5f866001600160a01b0316858760405161523d9190615ada565b5f6040518083038185875af1925050503d805f8114615277576040519150601f19603f3d011682016040523d82523d5f602084013e61527c565b606091505b509150915061528d87838387615298565b979650505050505050565b606083156153065782515f036152ff576001600160a01b0385163b6152ff5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611b2f565b5081613297565b613297838381511561531b5781518083602001fd5b8060405162461bcd60e51b8152600401611b2f91906153b9565b604080516080810182525f80825260208201819052918101829052606081019190915290565b6001600160e01b031981168114611a6c575f5ffd5b5f60208284031215615380575f5ffd5b8135611fa58161535b565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611fa5602083018461538b565b5f602082840312156153db575f5ffd5b5035919050565b6001600160a01b0391909116815260200190565b80356001600160a01b038116811461540c575f5ffd5b919050565b5f5f60408385031215615422575f5ffd5b61542b836153f6565b946020939093013593505050565b5f60208284031215615449575f5ffd5b611fa5826153f6565b602080825282518282018190525f918401906040840190835b8181101561548957835183526020938401939092019160010161546b565b509095945050505050565b803563ffffffff8116811461540c575f5ffd5b5f5f604083850312156154b8575f5ffd5b823591506154c860208401615494565b90509250929050565b80356001600160801b038116811461540c575f5ffd5b5f5f5f5f608085870312156154fa575f5ffd5b8435935061550a60208601615494565b92506040850135915061551f606086016154d1565b905092959194509250565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156155665761556661552a565b604052919050565b5f6001600160401b038211156155865761558661552a565b50601f01601f191660200190565b5f6155a66155a18461556e565b61553e565b90508281528383830111156155b9575f5ffd5b828260208301375f602084830101529392505050565b5f82601f8301126155de575f5ffd5b611fa583833560208501615594565b5f5f5f5f60808587031215615600575f5ffd5b615609856153f6565b9350615617602086016153f6565b925060408501356001600160401b03811115615631575f5ffd5b61563d878288016155cf565b92505060608501356001600160401b03811115615658575f5ffd5b615664878288016155cf565b91505092959194509250565b5f5f5f60608486031215615682575f5ffd5b61568b846153f6565b9250615699602085016153f6565b929592945050506040919091013590565b5f5f5f5f5f60a086880312156156be575f5ffd5b6156c7866153f6565b94506156d5602087016154d1565b93506156e360408701615494565b9250606086013591506156f8608087016154d1565b90509295509295909350565b5f60208284031215615714575f5ffd5b611fa582615494565b8015158114611a6c575f5ffd5b5f5f6040838503121561573b575f5ffd5b615744836153f6565b915060208301356157548161571d565b809150509250929050565b5f5f5f5f60808587031215615772575f5ffd5b61577b856153f6565b9350615789602086016153f6565b92506040850135915060608501356001600160401b038111156157aa575f5ffd5b8501601f810187136157ba575f5ffd5b61566487823560208401615594565b5f5f83601f8401126157d9575f5ffd5b5081356001600160401b038111156157ef575f5ffd5b6020830191508360208260051b8501011115615809575f5ffd5b9250929050565b5f5f5f60408486031215615822575f5ffd5b83356001600160401b03811115615837575f5ffd5b615843868287016157c9565b909790965060209590950135949350505050565b5f5f5f5f6080858703121561586a575f5ffd5b8435935061550a602086016154d1565b5f5f5f5f6040858703121561588d575f5ffd5b84356001600160401b038111156158a2575f5ffd5b6158ae878288016157c9565b90955093505060208501356001600160401b038111156158cc575f5ffd5b6158d8878288016157c9565b95989497509550505050565b5f5f604083850312156158f5575f5ffd5b6158fe836154d1565b91506154c860208401615494565b5f5f5f5f6080858703121561591f575f5ffd5b615928856154d1565b935061550a60208601615494565b5f5f60408385031215615947575f5ffd5b615950836153f6565b91506154c8602084016153f6565b600181811c9082168061597257607f821691505b6020821081036132fe57634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016159c9576159c96159a4565b5060010190565b63ffffffff8281168282160390811115610842576108426159a4565b8082028115828204841417610842576108426159a4565b634e487b7160e01b5f52601260045260245ffd5b5f82615a2557615a25615a03565b500490565b6001600160801b038281168282160390811115610842576108426159a4565b80820180821115610842576108426159a4565b81810381811115610842576108426159a4565b6001600160801b038181168382160190811115610842576108426159a4565b63ffffffff8181168382160190811115610842576108426159a4565b5f60208284031215615aba575f5ffd5b5051919050565b5f60208284031215615ad1575f5ffd5b611fa5826154d1565b5f82518060208501845e5f920191825250919050565b5f60208284031215615b00575f5ffd5b81516001600160401b03811115615b15575f5ffd5b8201601f81018413615b25575f5ffd5b8051615b336155a18261556e565b818152856020838501011115615b47575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f63ffffffff821680615b7957615b796159a4565b5f190192915050565b5f63ffffffff831680615b9757615b97615a03565b8063ffffffff84160491505092915050565b63ffffffff8181168382160290811690818114615bc857615bc86159a4565b5092915050565b5f82600f0b82600f0b0280600f0b9150808214615bc857615bc86159a4565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610842576108426159a4565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610842576108426159a4565b5f6001600160801b03831680615c6057615c60615a03565b6001600160801b03929092169190910492915050565b601f8211156113b157805f5260205f20601f840160051c81016020851015615c9b5750805b601f840160051c820191505b81811015614ba7575f8155600101615ca7565b81516001600160401b03811115615cd357615cd361552a565b615ce781615ce1845461595e565b84615c76565b6020601f821160018114615d19575f8315615d025750848201515b5f19600385901b1c1916600184901b178455614ba7565b5f84815260208120601f198516915b82811015615d485787850151825560209485019460019092019101615d28565b5084821015615d6557868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f60208284031215615d84575f5ffd5b8151611fa58161571d565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90611eec9083018461538b565b5f60208284031215615dd1575f5ffd5b8151611fa58161535b56fea264697066735822122067e3af8533ff98de13a52b43c98b05d159ba2d938981171b49d2e31bbb9f5c1464736f6c634300081b0033
Deployed Bytecode Sourcemap
165216:43604:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114891:316;;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;114891:316:0;;;;;;;;115791:149;;;:::i;:::-;;;;;;;:::i;117079:158::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;116898:115::-;;;;;;:::i;:::-;;:::i;:::-;;202359:104;202443:12;;-1:-1:-1;;;;;202443:12:0;202359:104;;202846:562;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;167377:68::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;167377:68:0;;;;;;;;;;-1:-1:-1;;;167377:68:0;;;;;;;;;3797:2:1;3786:22;;;3768:41;;3845:22;;;;3840:2;3825:18;;3818:50;3916:10;3904:23;;;3884:18;;;3877:51;;;;3964:23;;;3959:2;3944:18;;3937:51;3755:3;3740:19;167377:68:0;3545:449:1;185266:2031:0;;;;;;:::i;:::-;;:::i;168866:736::-;;;;;;:::i;:::-;;:::i;202471:96::-;202545:14;;-1:-1:-1;;;202545:14:0;;;;202471:96;;179866:154;;;;;;:::i;:::-;;:::i;202575:109::-;202656:20;;-1:-1:-1;;;;;202656:20:0;202575:109;;;-1:-1:-1;;;;;7084:32:1;;;7066:51;;7054:2;7039:18;202575:109:0;6920:203:1;203911:1754:0;;;;;;:::i;:::-;;:::i;:::-;;;7801:25:1;;;7789:2;7774:18;203911:1754:0;7655:177:1;180225:1505:0;;;;;;:::i;:::-;;:::i;202692:146::-;;;;;;:::i;:::-;;:::i;118465:134::-;;;;;;:::i;:::-;;:::i;201543:585::-;;;;;;:::i;:::-;;:::i;167504:23::-;;;;;-1:-1:-1;;;;;167504:23:0;;;167452:45;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;8199:2:1;8188:22;;;;8170:41;;8158:2;8143:18;167452:45:0;8026:191:1;159156:86:0;159227:7;;;;159156:86;;115604:120;;;;;;:::i;:::-;;:::i;115271:271::-;;;;;;:::i;:::-;;:::i;163451:103::-;;;:::i;169610:280::-;;;;;;:::i;:::-;;:::i;205669:54::-;;;:::i;167103:46::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;167103:46:0;;;;-1:-1:-1;;;167103:46:0;;;;;;;;;-1:-1:-1;;;167103:46:0;;;;;;;;;-1:-1:-1;;;;;8467:32:1;;;8449:51;;8536:32;;;;8531:2;8516:18;;8509:60;8617:10;8605:23;;;8585:18;;;8578:51;;;;8665:23;8660:2;8645:18;;8638:51;8436:3;8421:19;167103:46:0;8222:473:1;173202:1073:0;;;;;;:::i;:::-;;:::i;162716:147::-;;;:::i;167245:44::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;167245:44:0;;;;;;;;;;-1:-1:-1;;;167245:44:0;;;;;167296:19;;;;;;;;;;;;8874:10:1;8862:23;;;8844:42;;8832:2;8817:18;167296:19:0;8700:192:1;116009:153:0;;;:::i;191525:199::-;;;;;;:::i;:::-;;:::i;202235:116::-;;;;;;:::i;:::-;-1:-1:-1;;;;;202323:20:0;202298:5;202323:20;;;:14;:20;;;;;;;;;202235:116;;;;9069:4:1;9057:17;;;9039:36;;9027:2;9012:18;202235:116:0;8897:184:1;117309:146:0;;;;;;:::i;:::-;;:::i;180028:189::-;;;;;;:::i;:::-;;:::i;194305:4493::-;;;;;;:::i;:::-;;:::i;167157:47::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;190365:1152;;;;;;:::i;:::-;;:::i;201363:172::-;;;:::i;206080:2151::-;;;;;;:::i;:::-;;:::i;203412:495::-;;;;;;:::i;:::-;;:::i;208388:423::-;;;:::i;200675:368::-;;;;;;:::i;:::-;;:::i;198807:1858::-;;;;;;:::i;:::-;;:::i;201056:271::-;;;;;;:::i;:::-;;:::i;184867:390::-;;;;;;:::i;:::-;;:::i;167322:48::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;117526:213;;;;;;:::i;:::-;;:::i;163709:220::-;;;;;;:::i;:::-;;:::i;202136:68::-;;;:::i;114891:316::-;115004:4;-1:-1:-1;;;;;;115041:40:0;;-1:-1:-1;;;115041:40:0;;:105;;-1:-1:-1;;;;;;;115098:48:0;;-1:-1:-1;;;115098:48:0;115041:105;:158;;;-1:-1:-1;;;;;;;;;;112914:40:0;;;115163:36;115021:178;114891:316;-1:-1:-1;;114891:316:0:o;115791:149::-;115836:13;115862:23;115888:19;:17;:19::i;:::-;115862:45;;115925:1;:7;;115918:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;115791:149;:::o;117079:158::-;117146:7;117166:22;117180:7;117166:13;:22::i;:::-;;117208:21;117221:7;117208:12;:21::i;116898:115::-;116970:35;116979:2;116983:7;25439:10;116970:8;:35::i;:::-;116898:115;;:::o;202846:562::-;-1:-1:-1;;;;;202959:21:0;;202945:11;202959:21;;;:14;:21;;;;;;202907:25;;202959:21;;;-1:-1:-1;;;;;203002:20:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;203002:20:0;;202991:31;;203037:5;:10;;203046:1;203037:10;203033:31;;203049:15;202846:562;;;:::o;203033:31::-;203085:20;;203120:245;203146:12;;-1:-1:-1;;;203146:12:0;;;;203141:17;;203120:245;;;203201:5;-1:-1:-1;;;;;203185:21:0;:12;203194:2;203185:8;:12::i;:::-;-1:-1:-1;;;;;203185:21:0;;203181:173;;203252:2;203227:8;203236:12;203227:22;;;;;;;;:::i;:::-;;;;;;;;;;:27;203273:14;;;;:::i;:::-;;;;203326:5;203310:21;;:12;:21;203306:32;203333:5;203306:32;;203160:4;;203120:245;;;;203385:15;;202846:562;;;:::o;185266:2031::-;156226:21;:19;:21::i;:::-;158761:19:::1;:17;:19::i;:::-;185464:8:::2;169990;169972:15;:26;169968:56;;;170007:17;;-1:-1:-1::0;;;170007:17:0::2;;;;;;;;;;;169968:56;170098:24:::3;170125:15:::0;;;:6:::3;:15;::::0;;;;;;;;170098:42;;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;;;170098:42:0;;::::3;::::0;;;-1:-1:-1;;;170098:42:0;;::::3;;::::0;;::::3;::::0;;;;;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;;;;;-1:-1:-1;;;170098:42:0;::::3;::::0;;::::3;::::0;;;;185479:7;;170098:42;170155:15;;;;:57:::3;;;170200:4;:12;;;170174:38;;170181:15;170174:38;;;170155:57;170151:3018;;;170312:15;170352;170330:4;:12;;;:38;;;;:::i;:::-;170312:56:::0;-1:-1:-1;170469:17:0::3;166545:8;170490:29;166751:4;170489:41;170490:17:::0;::::3;:29;:::i;:::-;170489:41;;;;:::i;:::-;170469:61:::0;-1:-1:-1;170545:22:0::3;166751:4;170469:61:::0;170597:32:::3;166751:4:::0;166649::::3;170597:32;:::i;:::-;-1:-1:-1::0;;;;;170589:41:0::3;:53;;;;:::i;:::-;170588:67;;;;:::i;:::-;170570:85;::::0;166703:4:::3;170570:85;:::i;:::-;170545:110:::0;-1:-1:-1;170545:110:0;166649:4:::3;-1:-1:-1::0;;;;;170750:30:0;::::3;;170746:66;;;-1:-1:-1::0;166649:4:0::3;170746:66;166703:4;-1:-1:-1::0;;;;;170831:31:0;::::3;;170827:68;;;-1:-1:-1::0;166703:4:0::3;170827:68;171027:11:::0;;170998:17:::3;::::0;166751:4:::3;::::0;171019:30:::3;::::0;166545:8:::3;::::0;-1:-1:-1;;;;;171019:20:0::3;:30;:::i;:::-;171018:44;;;;:::i;:::-;170998:64;;171077:16;171104:9;171077:37;;171250:8;-1:-1:-1::0;;;;;171236:22:0::3;:4;:10;;;-1:-1:-1::0;;;;;171236:22:0::3;;;:70;;;;171300:6;171281:4;:15;;;171263:33;;:15;:33;;;;:::i;:::-;171262:44;171236:70;171232:1926;;;171429:10;::::0;::::3;::::0;171385:21:::3;::::0;-1:-1:-1;;;;;171429:14:0::3;::::0;171425:591:::3;;171468:20;166545:8;171492:29;166751:4;171491:41;171492:17:::0;::::3;:29;:::i;:::-;171491:41;;;;:::i;:::-;171468:64:::0;-1:-1:-1;171555:25:0::3;166751:4;171468:64:::0;171610:32:::3;166751:4:::0;166649::::3;171610:32;:::i;:::-;-1:-1:-1::0;;;;;171602:41:0::3;:56;;;;:::i;:::-;171601:70;;;;:::i;:::-;171583:88;::::0;166703:4:::3;171583:88;:::i;:::-;171555:116:::0;-1:-1:-1;171555:116:0;;-1:-1:-1;166649:4:0::3;-1:-1:-1::0;;;;;171763:30:0;::::3;;171759:66;;;166649:4;171795:30;;171759:66;166703:4;-1:-1:-1::0;;;;;171852:31:0;::::3;;171848:68;;;166703:4;171885:31;;171848:68;171445:491;;171425:591;;;-1:-1:-1::0;166703:4:0::3;171425:591;172089:11:::0;;172052:25:::3;::::0;166751:4:::3;::::0;172081:36:::3;::::0;-1:-1:-1;;;;;172081:36:0;;::::3;::::0;:20:::3;:36;:::i;:::-;172080:50;;;;:::i;:::-;172186:11:::0;;172052:78;;-1:-1:-1;172149:25:0::3;::::0;166751:4:::3;::::0;172178:36:::3;::::0;-1:-1:-1;;;;;172178:36:0;;::::3;::::0;:20:::3;:36;:::i;:::-;172177:50;;;;:::i;:::-;172149:78;;172349:17;172329;:37;172325:617;;;172391:16;172410:37;172430:17:::0;172410;:37:::3;:::i;:::-;172470:20;:41:::0;;172391:56;;-1:-1:-1;172391:56:0;;172470:20:::3;::::0;:41:::3;::::0;172391:56;;-1:-1:-1;;;;;172470:41:0::3;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;172470:41:0::3;;;;;-1:-1:-1::0;;;;;172470:41:0::3;;;;;;172368:163;172325:617;;;172561:17;172541;:37;172537:405;;;172603:16;172622:37;172642:17:::0;172622;:37:::3;:::i;:::-;172697:20;::::0;172603:56;;-1:-1:-1;;;;;;172697:20:0::3;172686:31:::0;::::3;172682:241;;;172746:20;:24:::0;;-1:-1:-1;;;;;;172746:24:0::3;::::0;;172682:241:::3;;;172858:20;:41:::0;;172890:8;;172858:20;::::3;::::0;:41:::3;::::0;172890:8;;-1:-1:-1;;;;;172858:41:0::3;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;172858:41:0::3;;;;;-1:-1:-1::0;;;;;172858:41:0::3;;;;;;172682:241;172580:362;172537:405;-1:-1:-1::0;;;173039:15:0::3;::::0;;;:6:::3;:15;::::0;;;;:32;;-1:-1:-1;;;;;173039:32:0;;::::3;-1:-1:-1::0;;;173039:32:0::3;::::0;::::3;;::::0;;-1:-1:-1;173090:26:0::3;:52:::0;;::::3;173126:15;173090:52;-1:-1:-1::0;;;173090:52:0::3;-1:-1:-1::0;;173090:52:0;;::::3;;::::0;;171232:1926:::3;170214:2955;;;;;;170151:3018;185523:10:::4;185503:16;185511:7:::0;185503::::4;:16::i;:::-;-1:-1:-1::0;;;;;185503:30:0::4;;185499:58;;185542:15;;-1:-1:-1::0;;;185542:15:0::4;;;;;;;;;;;185499:58;185578:24;185605:15:::0;;;:6:::4;:15;::::0;;;;;;;185578:42;;::::4;::::0;::::4;::::0;;;;-1:-1:-1;;;;;185578:42:0;;::::4;::::0;;;-1:-1:-1;;;185578:42:0;;::::4;;::::0;;::::4;::::0;;;;;;;::::4;::::0;::::4;::::0;;::::4;::::0;;;;;;;-1:-1:-1;;;185578:42:0;::::4;::::0;;::::4;::::0;;;;;185635:16;185631:44:::4;;185660:15;;-1:-1:-1::0;;;185660:15:0::4;;;;;;;;;;;185631:44;185696:17;185750:15;185728:38;;:4;:12;;;:38;;;185724:328;;;185848:44;185874:18:::0;185855:15:::4;185848:44;:::i;:::-;185835:57;;185724:328;;;186022:18;186007:4;:12;;;:33;;;;:::i;:::-;185994:46;;185724:328;186062:29;186094:36;186114:15;186094:10:::0;:36:::4;:::i;:::-;186062:68:::0;-1:-1:-1;166545:8:0::4;186145:32;::::0;::::4;;186141:62;;;186186:17;;-1:-1:-1::0;;;186186:17:0::4;;;;;;;;;;;186141:62;186291:16;186310:31;186329:4;:11;;;186310:18;:31::i;:::-;186291:50;;186352:18;186373:54;186394:8;186404:22;186373:20;:54::i;:::-;186352:75;;186455:13;-1:-1:-1::0;;;;;186442:26:0::4;:10;-1:-1:-1::0;;;;;186442:26:0::4;;186438:57;;;186477:18;;-1:-1:-1::0;;;186477:18:0::4;;;;;;;;;;;186438:57;186551:55;186573:7;186582:4;:11;;;186595:10;186551:21;:55::i;:::-;186650:314;186676:7;186698:121;;;;;;;;186754:4;:11;;;186698:121;;;;;;186791:4;:12;;;186698:121;;;;::::0;186834:119:::4;;;;;;;;186890:4;:11;;;186834:119;;;;;;186927:10;186834:119;;;;::::0;186650:11:::4;:314::i;:::-;187033:173;;;;;;;;187069:4;:11;;;-1:-1:-1::0;;;;;187033:173:0::4;;;;;187186:8;-1:-1:-1::0;;;;;187033:173:0::4;;;;;187104:10;187033:173;;;;;;187148:15;187033:173;;;;::::0;187015:6:::4;:15;187022:7;187015:15;;;;;;;;;;;:191;;;;;;;;;;;;;-1:-1:-1::0;;;;;187015:191:0::4;;;;;-1:-1:-1::0;;;;;187015:191:0::4;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;187015:191:0::4;;;;;-1:-1:-1::0;;;;;187015:191:0::4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;187257:7;187245:10;-1:-1:-1::0;;;;;187232:57:0::4;;187266:10;187278;187232:57;;;;;;15862:10:1::0;15850:23;;;;15832:42;;-1:-1:-1;;;;;15910:32:1;15905:2;15890:18;;15883:60;15820:2;15805:18;;15660:289;187232:57:0::4;;;;;;;;185488:1809;;;;;170087:3101:::3;170035:1;158791::::2;156270:20:::0;155487:1;156790:7;:22;156607:213;156270:20;185266:2031;;;;:::o;168866:736::-;24567:21;19883:15;;-1:-1:-1;;;19883:15:0;;;;19882:16;;-1:-1:-1;;;;;19930:14:0;19736:30;20315:16;;:34;;;;;20335:14;20315:34;20295:54;;20360:17;20380:11;-1:-1:-1;;;;;20380:16:0;20395:1;20380:16;:50;;;;-1:-1:-1;20408:4:0;20400:25;:30;20380:50;20360:70;;20448:12;20447:13;:30;;;;;20465:12;20464:13;20447:30;20443:93;;;20501:23;;-1:-1:-1;;;20501:23:0;;;;;;;;;;;20443:93;20546:18;;-1:-1:-1;;;;;;20546:18:0;20563:1;20546:18;;;20575:69;;;;20610:22;;-1:-1:-1;;;;20610:22:0;-1:-1:-1;;;20610:22:0;;;20575:69;-1:-1:-1;;;;;169062:26:0;::::1;::::0;;:77:::1;;-1:-1:-1::0;;;;;;169108:31:0;::::1;::::0;169062:77:::1;169058:103;;;169148:13;;-1:-1:-1::0;;;169148:13:0::1;;;;;;;;;;;169058:103;169186:27;169200:4;169206:6;169186:13;:27::i;:::-;169224:24;:22;:24::i;:::-;169259:17;:15;:17::i;:::-;169287:26;169302:10;169287:14;:26::i;:::-;169326:8;:6;:8::i;:::-;169345:12;:46:::0;;-1:-1:-1;;;;;169345:46:0;;::::1;-1:-1:-1::0;;;;;;169345:46:0;;::::1;;::::0;;;169402:25:::1;:45:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;169345:12:::1;169497:15:::0;;:12:::1;:15;::::0;:19;:42;;169578:15:::1;169497;169550:44:::0;;::::1;-1:-1:-1::0;;169526:12:0::1;169497:42:::0;;;::::1;-1:-1:-1::0;;;169497:42:0::1;169550:44:::0;;;;-1:-1:-1;;;;;;169550:44:0;;;;;;;::::1;::::0;;20666:104;;;;20701:23;;-1:-1:-1;;;;20701:23:0;;;20744:14;;-1:-1:-1;16107:50:1;;20744:14:0;;16095:2:1;16080:18;20744:14:0;;;;;;;20666:104;19668:1109;;;;;168866:736;;;;:::o;179866:154::-;179975:36;179994:4;179999:2;180003:7;179975:18;:36::i;:::-;179866:154;;;:::o;203911:1754::-;204126:15;156226:21;:19;:21::i;:::-;158761:19:::1;:17;:19::i;:::-;204107:8:::2;169990;169972:15;:26;169968:56;;;170007:17;;-1:-1:-1::0;;;170007:17:0::2;;;;;;;;;;;169968:56;204154:6:::3;-1:-1:-1::0;;;;;204154:11:0::3;204164:1;204154:11:::0;204150:39:::3;;204174:15;;-1:-1:-1::0;;;204174:15:0::3;;;;;;;;;;;204150:39;204200:17;::::0;::::3;::::0;;:43:::3;;-1:-1:-1::0;166545:8:0::3;204221:22;::::0;::::3;;204200:43;204196:73;;;204252:17;;-1:-1:-1::0;;;204252:17:0::3;;;;;;;;;;;204196:73;-1:-1:-1::0;;;;;204280:23:0;::::3;204276:49;;204312:13;;-1:-1:-1::0;;;204312:13:0::3;;;;;;;;;;;204276:49;-1:-1:-1::0;;;;;204336:25:0;::::3;;::::0;;;:14:::3;:25;::::0;;;;;166806:3:::3;204336:47;:25:::0;;::::3;:47;204332:77;;204392:17;;-1:-1:-1::0;;;204392:17:0::3;;;;;;;;;;;204332:77;204422:17;204442:38;204468:12:::0;204449:15:::3;204442:38;:::i;:::-;204422:58;;204494:13;204509:18;204531:61;204556:6;204564:12;204578:13;204531:24;:61::i;:::-;204493:99;;;;204637:28;204668:90;;;;;;;;204716:6;204668:90;;;;;;204740:10;204668:90;;;;::::0;204637:121:::3;;204813:44;204825:1;204828:19;;;;;;;;204842:1;204828:19;;;;;;204845:1;204828:19;;;;::::0;204849:7:::3;204813:11;:44::i;:::-;204934:12;::::0;:37:::3;::::0;-1:-1:-1;;;204934:37:0;;204910:21:::3;::::0;-1:-1:-1;;;;;204934:12:0::3;::::0;:22:::3;::::0;:37:::3;::::0;204965:4:::3;::::0;204934:37:::3;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;204978:12;::::0;204910:61;;-1:-1:-1;204978:64:0::3;::::0;-1:-1:-1;;;;;204978:12:0::3;205008:10;205028:4;-1:-1:-1::0;;;;;204978:64:0;::::3;:29;:64::i;:::-;205094:22;-1:-1:-1::0;;;;;205094:22:0;::::3;:13:::0;:22:::3;:::i;:::-;205053:12;::::0;:37:::3;::::0;-1:-1:-1;;;205053:37:0;;-1:-1:-1;;;;;205053:12:0;;::::3;::::0;:22:::3;::::0;:37:::3;::::0;205084:4:::3;::::0;205053:37:::3;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:63;205049:102;;205135:16;;-1:-1:-1::0;;;205135:16:0::3;;;;;;;;;;;205049:102;205195:12;:14:::0;;::::3;;-1:-1:-1::0;;;205195:14:0;;::::3;::::0;::::3;::::0;;::::3;::::0;;::::3;;-1:-1:-1::0;;;;205195:14:0;;::::3;::::0;;;::::3;::::0;;;-1:-1:-1;;;;;205220:25:0;::::3;-1:-1:-1::0;205220:25:0;;;:14:::3;:25;::::0;;;;:27;;::::3;::::0;;::::3;::::0;;::::3;::::0;;::::3;-1:-1:-1::0;;205220:27:0;;::::3;::::0;;;::::3;::::0;;;205195:14;-1:-1:-1;205267:29:0::3;205235:9:::0;205195:14;205267:9:::3;:29::i;:::-;205327:145;::::0;;::::3;::::0;::::3;::::0;;-1:-1:-1;;;;;205327:145:0;;::::3;::::0;;;;::::3;;::::0;;::::3;::::0;;;::::3;::::0;;::::3;::::0;;;;;;205425:15:::3;205327:145:::0;::::3;::::0;;;;;;-1:-1:-1;205309:15:0;;;:6:::3;:15:::0;;;;;;;:163;;;;;::::3;-1:-1:-1::0;;;205309:163:0::3;::::0;;;::::3;::::0;;;::::3;::::0;;;;;;::::3;::::0;;;;;::::3;-1:-1:-1::0;;;205309:163:0::3;-1:-1:-1::0;;;;;;205309:163:0;;;;;;::::3;::::0;;;;;;;::::3;::::0;;205485:50:::3;205316:7:::0;205359:6;205524:10;205485:21:::3;:50::i;:::-;205571:19;::::0;;;;::::3;::::0;;;-1:-1:-1;205571:19:0;;;::::3;::::0;::::3;::::0;205550:50:::3;::::0;205562:7;;205592;205550:11:::3;:50::i;:::-;205614:47;::::0;;-1:-1:-1;;;;;16547:32:1;;16529:51;;16628:10;16616:23;;16611:2;16596:18;;16589:51;205633:7:0;;-1:-1:-1;;;;;205614:47:0;::::3;::::0;::::3;::::0;16502:18:1;205614:47:0::3;;;;;;;204143:1522;;;;;158791:1:::2;156270:20:::0;155487:1;156790:7;:22;156607:213;156270:20;203911:1754;;;;;;;:::o;180225:1505::-;156226:21;:19;:21::i;:::-;158761:19:::1;:17;:19::i;:::-;180307:13:::2;180323:17;180332:7;180323:8;:17::i;:::-;180307:33:::0;-1:-1:-1;;;;;;180355:19:0;::::2;180351:48;;180383:16;;-1:-1:-1::0;;;180383:16:0::2;;;;;;;;;;;180351:48;-1:-1:-1::0;;;;;180414:19:0;::::2;180423:10;180414:19;180410:47;;180442:15;;-1:-1:-1::0;;;180442:15:0::2;;;;;;;;;;;180410:47;180478:24;180505:15:::0;;;:6:::2;:15;::::0;;;;;;;180478:42;;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;;;180478:42:0;;::::2;::::0;;;-1:-1:-1;;;180478:42:0;;::::2;;::::0;;::::2;::::0;;;;;;;::::2;::::0;::::2;::::0;;::::2;::::0;;;;;;;-1:-1:-1;;;180478:42:0;::::2;::::0;;::::2;::::0;;;;;180535:16;180531:44:::2;;180560:15;;-1:-1:-1::0;;;180560:15:0::2;;;;;;;;;;;180531:44;180616:4;:12;;;180590:38;;180597:15;180590:38;;;180586:67;;;180637:16;;-1:-1:-1::0;;;180637:16:0::2;;;;;;;;;;;180586:67;180691:11:::0;;180810:20:::2;::::0;-1:-1:-1;;;;;180810:20:0;;::::2;180801:29:::0;;::::2;;180797:149;;;180847:20;:24:::0;;-1:-1:-1;;;;;;180847:24:0::2;::::0;;180797:149:::2;;;180904:20;:30:::0;;180928:6;;180904:20;::::2;::::0;:30:::2;::::0;180928:6;;-1:-1:-1;;;;;180904:30:0::2;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;180904:30:0::2;;;;;-1:-1:-1::0;;;;;180904:30:0::2;;;;;;180797:149;181002:15;::::0;;;:6:::2;:15;::::0;;;;;;;180995:22;;;;::::2;::::0;;-1:-1:-1;;;;;;180995:22:0;;;181104:104;;;;::::2;::::0;;::::2;::::0;;::::2;::::0;;181184:12;;::::2;::::0;180995:22:::2;181104:104;::::0;;::::2;::::0;181302:19;;;;::::2;::::0;;;;;;;;::::2;::::0;;;;181104:104;181272:50:::2;::::0;181009:7;;181104:104;;181272:11:::2;:50::i;:::-;181387:23;::::0;;;:14:::2;:23;::::0;;;;181380:30;;-1:-1:-1;;181380:30:0::2;::::0;;181478:12:::2;::::0;:45:::2;::::0;-1:-1:-1;;;;;181478:12:0::2;181504:10;-1:-1:-1::0;;;;;181478:45:0;::::2;:25;:45::i;:::-;181570:14;181576:7;181570:5;:14::i;:::-;181635:10;181620:26;::::0;;;:14:::2;:26;::::0;;;;;;;;:28;;-1:-1:-1;;181620:28:0;::::2;;::::0;;::::2;-1:-1:-1::0;;181620:28:0;;;::::2;;::::0;;181685:37;;-1:-1:-1;;;;;7084:32:1;;7066:51;;181706:7:0;;181635:10;181685:37:::2;::::0;7039:18:1;181685:37:0::2;;;;;;;180296:1434;;;;156270:20:::0;155487:1;156790:7;:22;156607:213;156270:20;180225:1505;:::o;202692:146::-;162602:13;:11;:13::i;:::-;-1:-1:-1;;;;;202762:23:0;::::1;202758:49;;202794:13;;-1:-1:-1::0;;;202794:13:0::1;;;;;;;;;;;202758:49;202814:8;:20:::0;;-1:-1:-1;;;;;;202814:20:0::1;-1:-1:-1::0;;;;;202814:20:0;;;::::1;::::0;;;::::1;::::0;;202692:146::o;118465:134::-;118552:39;118569:4;118575:2;118579:7;118552:39;;;;;;;;;;;;:16;:39::i;201543:585::-;156226:21;:19;:21::i;:::-;201628:14:::1;::::0;-1:-1:-1;;;201628:14:0;::::1;;;201620:48;;;::::0;-1:-1:-1;;;201620:48:0;;16853:2:1;201620:48:0::1;::::0;::::1;16835:21:1::0;16892:2;16872:18;;;16865:30;-1:-1:-1;;;16911:18:1;;;16904:51;16972:18;;201620:48:0::1;;;;;;;;;201703:10;201683:16;201691:7:::0;201683::::1;:16::i;:::-;-1:-1:-1::0;;;;;201683:30:0::1;;201679:58;;201722:15;;-1:-1:-1::0;;;201722:15:0::1;;;;;;;;;;;201679:58;201758:24;201785:15:::0;;;:6:::1;:15;::::0;;;;;;;201758:42;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;201758:42:0;;::::1;::::0;;;-1:-1:-1;;;201758:42:0;;::::1;;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;201758:42:0;::::1;::::0;;::::1;::::0;;;;201867:15;;;;;;;201860:22;;;-1:-1:-1;;;;;;201860:22:0;;;;201893:14:::1;201792:7:::0;201893:5:::1;:14::i;:::-;201958:10;201943:26;::::0;;;:14:::1;:26;::::0;;;;:28;;-1:-1:-1;;201943:28:0;::::1;;::::0;;::::1;-1:-1:-1::0;;201943:28:0;;;::::1;;::::0;;202003:12:::1;::::0;:45:::1;::::0;-1:-1:-1;;;;;202003:12:0;;::::1;::::0;-1:-1:-1;;;;;202003:45:0;::::1;:25;:45::i;:::-;202074:46;::::0;-1:-1:-1;;;;;7084:32:1;;7066:51;;202104:7:0;;202092:10:::1;::::0;202074:46:::1;::::0;7054:2:1;7039:18;202074:46:0::1;;;;;;;201609:519;;156270:20:::0;155487:1;156790:7;:22;156607:213;115604:120;115667:7;115694:22;115708:7;115694:13;:22::i;115271:271::-;115334:7;115354:23;115380:19;:17;:19::i;:::-;115354:45;-1:-1:-1;;;;;;115414:19:0;;115410:89;;115484:1;115457:30;;-1:-1:-1;;;115457:30:0;;;;;;;;:::i;115410:89::-;-1:-1:-1;;;;;115516:18:0;;;;;;;:11;;;;:18;;-1:-1:-1;115516:18:0;;;;;115271:271::o;163451:103::-;162602:13;:11;:13::i;:::-;163516:30:::1;163543:1;163516:18;:30::i;:::-;163451:103::o:0;169610:280::-;162602:13;:11;:13::i;:::-;-1:-1:-1;;;;;169690:26:0;::::1;169686:52;;169725:13;;-1:-1:-1::0;;;169725:13:0::1;;;;;;;;;;;169686:52;169761:12;::::0;-1:-1:-1;;;;;169761:12:0::1;169753:35:::0;169749:74:::1;;169790:33;::::0;-1:-1:-1;;;169790:33:0;;17203:2:1;169790:33:0::1;::::0;::::1;17185:21:1::0;17242:2;17222:18;;;17215:30;-1:-1:-1;;;17261:18:1;;;17254:53;17324:18;;169790:33:0::1;17001:347:1::0;169749:74:0::1;169834:12;:48:::0;;-1:-1:-1;;;;;;169834:48:0::1;-1:-1:-1::0;;;;;169834:48:0;;;::::1;::::0;;;::::1;::::0;;169610:280::o;205669:54::-;162602:13;:11;:13::i;:::-;205710:8:::1;:6;:8::i;173202:1073::-:0;173270:7;173317:15;;;:6;:15;;;;;;;;173290:42;;;;;;;;;-1:-1:-1;;;;;173290:42:0;;;;;-1:-1:-1;;;173290:42:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;173290:42:0;;;;;;;;;173354:15;173347:39;;173343:67;;-1:-1:-1;166703:4:0;;173202:1073;-1:-1:-1;;173202:1073:0:o;173343:67::-;173517:15;173557;173535:4;:12;;;:38;;;;:::i;:::-;173517:56;-1:-1:-1;173744:17:0;166545:8;173765:29;166751:4;173764:41;173765:17;;:29;:::i;:::-;173764:41;;;;:::i;:::-;173744:61;-1:-1:-1;173912:22:0;166751:4;173744:61;173964:32;166751:4;166649;173964:32;:::i;:::-;-1:-1:-1;;;;;173956:41:0;:53;;;;:::i;:::-;173955:67;;;;:::i;:::-;173937:85;;166703:4;173937:85;:::i;:::-;173912:110;-1:-1:-1;173912:110:0;166649:4;-1:-1:-1;;;;;174112:27:0;;;174108:54;;;-1:-1:-1;166649:4:0;;173202:1073;-1:-1:-1;;;;;;173202:1073:0:o;174108:54::-;166703:4;-1:-1:-1;;;;;174177:28:0;;;174173:56;;;-1:-1:-1;166703:4:0;;173202:1073;-1:-1:-1;;;;;;173202:1073:0:o;174173:56::-;174257:10;173202:1073;-1:-1:-1;;;;;;173202:1073:0:o;162716:147::-;161547:22;162847:8;-1:-1:-1;;;;;162847:8:0;;162716:147::o;116009:153::-;116056:13;116082:23;116108:19;:17;:19::i;:::-;116082:45;;116145:1;:9;;116138:16;;;;;:::i;191525:199::-;191652:5;;;;;;191594:7;191639:19;;;:12;:19;;;;;;;;191614:44;;;;;;;;;;;;;;;-1:-1:-1;;;191614:44:0;;;;;;;;;;;;191652:5;191614:44;;;;;;;;;;;;-1:-1:-1;;;191614:44:0;;;;;;;;;191594:7;191684:31;191614:44;191705:9;191684;:31::i;:::-;191669:47;191525:199;-1:-1:-1;;;191525:199:0:o;117309:146::-;117395:52;25439:10;117428:8;117438;117395:18;:52::i;180028:189::-;180162:47;180185:4;180191:2;180195:7;180204:4;180162:22;:47::i;194305:4493::-;156226:21;:19;:21::i;:::-;158761:19:::1;:17;:19::i;:::-;194442:8:::2;169990;169972:15;:26;169968:56;;;170007:17;;-1:-1:-1::0;;;170007:17:0::2;;;;;;;;;;;169968:56;194485:1:::3;194467:19:::0;::::3;194463:47;;;194495:15;;-1:-1:-1::0;;;194495:15:0::3;;;;;;;;;;;194463:47;194603:19;::::0;194700:15:::3;194603:19:::0;194789:1070:::3;194809:19:::0;;::::3;194789:1070;;;194878:10;194854:20;194862:8:::0;;194871:1;194862:11;;::::3;;;;;:::i;:::-;;;;;;;194854:7;:20::i;:::-;-1:-1:-1::0;;;;;194854:34:0::3;;194850:62;;194897:15;;-1:-1:-1::0;;;194897:15:0::3;;;;;;;;;;;194850:62;194941:24;194968:6;:19;194975:8;;194984:1;194975:11;;;;;;;:::i;:::-;;::::0;;::::3;::::0;;;::::3;;194968:19:::0;;-1:-1:-1;194968:19:0;;::::3;::::0;;;;;;;;-1:-1:-1;194968:19:0;;;194941:46;;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;;;194941:46:0;;::::3;::::0;;;-1:-1:-1;;;194941:46:0;;::::3;;::::0;;::::3;::::0;;;;;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;;;;;-1:-1:-1;;;194941:46:0;::::3;::::0;;::::3;::::0;;;;;;-1:-1:-1;195006:16:0;195002:44:::3;;195031:15;;-1:-1:-1::0;;;195031:15:0::3;;;;;;;;;;;195002:44;195141:11:::0;;195126:26:::3;::::0;;::::3;:::i;:::-;;;195257:11;195242:26;;:4;:12;;;:26;;;:58;;;;;195287:13;195272:28;;:4;:12;;;:28;;;195242:58;195238:127;;;195337:4;:12;;;195321:28;;195238:127;195492:23;195518:33;195539:8;;195548:1;195539:11;;;;;;;:::i;:::-;;;;;;;195518:20;:33::i;:::-;195600:11:::0;;195492:59;;-1:-1:-1;195566:22:0::3;::::0;166751:4:::3;::::0;195592:38:::3;::::0;-1:-1:-1;;;;;195592:38:0;;::::3;::::0;:20:::3;:38;:::i;:::-;195591:52;;;;:::i;:::-;195679:20;::::0;195566:77;;-1:-1:-1;;;;;;195679:20:0::3;195662:37:::0;::::3;195658:190;;;195720:20;:24:::0;;-1:-1:-1;;;;;;195720:24:0::3;::::0;;195658:190:::3;;;195785:20;:47:::0;;195817:14;;195785:20;::::3;::::0;:47:::3;::::0;195817:14;;-1:-1:-1;;;;;195785:47:0::3;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;195785:47:0::3;;;;;-1:-1:-1::0;;;;;195785:47:0::3;;;;;;195658:190;-1:-1:-1::0;;;194830:3:0::3;;194789:1070;;;;195977:11;195960:28;;:13;:28;;;195956:183;;196107:20;:11:::0;196121:6:::3;196107:20;:::i;:::-;196091:36;;195956:183;196225:9;196220:661;196240:19:::0;;::::3;196220:661;;;196281:24;196308:6;:19;196315:8;;196324:1;196315:11;;;;;;;:::i;:::-;;::::0;;::::3;::::0;;;::::3;;196308:19:::0;;-1:-1:-1;196308:19:0;;::::3;::::0;;;;;;;;-1:-1:-1;196308:19:0;196281:46;;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;;;196281:46:0;;::::3;::::0;;-1:-1:-1;;;196281:46:0;;::::3;;::::0;;::::3;::::0;;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;;;;-1:-1:-1;;;196281:46:0;;::::3;::::0;::::3;::::0;;;;196453:121;;;;::::3;::::0;;;196509:11;;196453:121:::3;;::::0;;196546:12;;196453:121:::3;::::0;;::::3;::::0;;;;196281:46;;-1:-1:-1;196671:54:0::3;196683:8:::0;;196692:1;196683:11;;::::3;;;;;:::i;:::-;;;;;;;196696:7;196705:19;;;;;;;;196719:1;196705:19;;;;;;196722:1;196705:19;;;;::::0;196671:11:::3;:54::i;:::-;196817:6;:19;196824:8;;196833:1;196824:11;;;;;;;:::i;:::-;;::::0;;::::3;::::0;;;::::3;;196817:19:::0;;-1:-1:-1;196817:19:0;::::3;::::0;;;;;;-1:-1:-1;196817:19:0;;;196810:26;;;;::::3;::::0;;-1:-1:-1;;;;;;196810:26:0;;;196851:18:::3;196857:8:::0;;196866:1;196857:11;;::::3;;;;;:::i;:::-;;;;;;;196851:5;:18::i;:::-;-1:-1:-1::0;;196261:3:0::3;;196220:661;;;-1:-1:-1::0;196971:12:0::3;::::0;-1:-1:-1;;;196971:12:0;::::3;;;196994:126;197033:1;197001:20;;::::0;::::3;:8;:20::i;:::-;-1:-1:-1::0;;;;;197001:34:0::3;;196994:126;;197081:12;;196994:126;;;197223:14;:10:::0;197236:1:::3;197223:14;:::i;:::-;197208:12;:29:::0;;-1:-1:-1;;;;197208:29:0::3;-1:-1:-1::0;;;197208:29:0::3;::::0;;::::3;;;::::0;;197285:33:::3;::::0;197295:10:::3;::::0;197285:33;::::3;:9;:33::i;:::-;197394:24;197421:27;197437:11:::0;197421:13;:27:::3;:::i;:::-;197394:54:::0;-1:-1:-1;166545:8:0::3;197463:27;::::0;::::3;;197459:57;;;197499:17;;-1:-1:-1::0;;;197499:17:0::3;;;;;;;;;;;197459:57;197527:16;166545:8;197555:32;166751:4;-1:-1:-1::0;;;;;197555:20:0;::::3;:32;:::i;:::-;197554:44;;;;:::i;:::-;197675:164;::::0;;::::3;::::0;::::3;::::0;;-1:-1:-1;;;;;197675:164:0;;::::3;::::0;;;;::::3;;::::0;;::::3;::::0;;;::::3;::::0;;::::3;::::0;;;;;;;;::::3;::::0;;;;;;197654:18;;::::3;-1:-1:-1::0;197654:18:0;;;:6:::3;:18:::0;;;;;:185;;;;;::::3;-1:-1:-1::0;;;197654:185:0::3;::::0;;;::::3;::::0;;;::::3;::::0;;;;;;;::::3;::::0;;;;;::::3;-1:-1:-1::0;;;197654:185:0::3;-1:-1:-1::0;;;;;;197654:185:0;;;;;;::::3;::::0;;;;;;;::::3;::::0;;197939:110;;;;::::3;::::0;;::::3;::::0;;::::3;::::0;;;;::::3;::::0;;;;198130:19;;;;::::3;::::0;;;;;;;::::3;::::0;;;;197527:72;;-1:-1:-1;197939:110:0;198106:53:::3;::::0;197939:110;198106:11:::3;:53::i;:::-;198226:18;198247:49;198268:8;198278:17;198247:20;:49::i;:::-;198226:70:::0;-1:-1:-1;198386:25:0::3;166751:4;198415:33;-1:-1:-1::0;;;;;198415:33:0;;::::3;::::0;:20;::::3;:33;:::i;:::-;198414:47;;;;:::i;:::-;198472:20;:50:::0;;198386:75;;-1:-1:-1;198386:75:0;;198472:20:::3;::::0;:50:::3;::::0;198386:75;;-1:-1:-1;;;;;198472:50:0::3;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;198472:50:0::3;;;;;-1:-1:-1::0;;;;;198472:50:0::3;;;;;;198673:8;;:15;;198638:14;:26;198653:10;-1:-1:-1::0;;;;;198638:26:0::3;-1:-1:-1::0;;;;;198638:26:0::3;;;;;;;;;;;;;;;;;;;;;;:51;198692:1;198638:55;198603:14;:26;198618:10;-1:-1:-1::0;;;;;198603:26:0::3;-1:-1:-1::0;;;;;198603:26:0::3;;;;;;;;;;;;;:91;;;;;;;;;;;;;;;;;;198751:10;198731:59;;198739:10;-1:-1:-1::0;;;;;198731:59:0::3;;198763:11;198776:13;198731:59;;;;;;-1:-1:-1::0;;;;;16547:32:1;;;;16529:51;;16628:10;16616:23;16611:2;16596:18;;16589:51;16517:2;16502:18;;16357:289;198731:59:0::3;;;;;;;;194452:4346;;;;;;;;;158791:1:::2;156270:20:::0;155487:1;156790:7;:22;156607:213;190365:1152;156226:21;:19;:21::i;:::-;158761:19:::1;:17;:19::i;:::-;190570:8:::2;169990;169972:15;:26;169968:56;;;170007:17;;-1:-1:-1::0;;;170007:17:0::2;;;;;;;;;;;169968:56;170098:24:::3;170125:15:::0;;;:6:::3;:15;::::0;;;;;;;;170098:42;;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;;;170098:42:0;;::::3;::::0;;;-1:-1:-1;;;170098:42:0;;::::3;;::::0;;::::3;::::0;;;;;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;;;;;-1:-1:-1;;;170098:42:0;::::3;::::0;;::::3;::::0;;;;190585:7;;170098:42;170155:15;;;;:57:::3;;;170200:4;:12;;;170174:38;;170181:15;170174:38;;;170155:57;170151:3018;;;170312:15;170352;170330:4;:12;;;:38;;;;:::i;:::-;170312:56:::0;-1:-1:-1;170469:17:0::3;166545:8;170490:29;166751:4;170489:41;170490:17:::0;::::3;:29;:::i;:::-;170489:41;;;;:::i;:::-;170469:61:::0;-1:-1:-1;170545:22:0::3;166751:4;170469:61:::0;170597:32:::3;166751:4:::0;166649::::3;170597:32;:::i;:::-;-1:-1:-1::0;;;;;170589:41:0::3;:53;;;;:::i;:::-;170588:67;;;;:::i;:::-;170570:85;::::0;166703:4:::3;170570:85;:::i;:::-;170545:110:::0;-1:-1:-1;170545:110:0;166649:4:::3;-1:-1:-1::0;;;;;170750:30:0;::::3;;170746:66;;;-1:-1:-1::0;166649:4:0::3;170746:66;166703:4;-1:-1:-1::0;;;;;170831:31:0;::::3;;170827:68;;;-1:-1:-1::0;166703:4:0::3;170827:68;171027:11:::0;;170998:17:::3;::::0;166751:4:::3;::::0;171019:30:::3;::::0;166545:8:::3;::::0;-1:-1:-1;;;;;171019:20:0::3;:30;:::i;:::-;171018:44;;;;:::i;:::-;170998:64;;171077:16;171104:9;171077:37;;171250:8;-1:-1:-1::0;;;;;171236:22:0::3;:4;:10;;;-1:-1:-1::0;;;;;171236:22:0::3;;;:70;;;;171300:6;171281:4;:15;;;171263:33;;:15;:33;;;;:::i;:::-;171262:44;171236:70;171232:1926;;;171429:10;::::0;::::3;::::0;171385:21:::3;::::0;-1:-1:-1;;;;;171429:14:0::3;::::0;171425:591:::3;;171468:20;166545:8;171492:29;166751:4;171491:41;171492:17:::0;::::3;:29;:::i;:::-;171491:41;;;;:::i;:::-;171468:64:::0;-1:-1:-1;171555:25:0::3;166751:4;171468:64:::0;171610:32:::3;166751:4:::0;166649::::3;171610:32;:::i;:::-;-1:-1:-1::0;;;;;171602:41:0::3;:56;;;;:::i;:::-;171601:70;;;;:::i;:::-;171583:88;::::0;166703:4:::3;171583:88;:::i;:::-;171555:116:::0;-1:-1:-1;171555:116:0;;-1:-1:-1;166649:4:0::3;-1:-1:-1::0;;;;;171763:30:0;::::3;;171759:66;;;166649:4;171795:30;;171759:66;166703:4;-1:-1:-1::0;;;;;171852:31:0;::::3;;171848:68;;;166703:4;171885:31;;171848:68;171445:491;;171425:591;;;-1:-1:-1::0;166703:4:0::3;171425:591;172089:11:::0;;172052:25:::3;::::0;166751:4:::3;::::0;172081:36:::3;::::0;-1:-1:-1;;;;;172081:36:0;;::::3;::::0;:20:::3;:36;:::i;:::-;172080:50;;;;:::i;:::-;172186:11:::0;;172052:78;;-1:-1:-1;172149:25:0::3;::::0;166751:4:::3;::::0;172178:36:::3;::::0;-1:-1:-1;;;;;172178:36:0;;::::3;::::0;:20:::3;:36;:::i;:::-;172177:50;;;;:::i;:::-;172149:78;;172349:17;172329;:37;172325:617;;;172391:16;172410:37;172430:17:::0;172410;:37:::3;:::i;:::-;172470:20;:41:::0;;172391:56;;-1:-1:-1;172391:56:0;;172470:20:::3;::::0;:41:::3;::::0;172391:56;;-1:-1:-1;;;;;172470:41:0::3;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;172470:41:0::3;;;;;-1:-1:-1::0;;;;;172470:41:0::3;;;;;;172368:163;172325:617;;;172561:17;172541;:37;172537:405;;;172603:16;172622:37;172642:17:::0;172622;:37:::3;:::i;:::-;172697:20;::::0;172603:56;;-1:-1:-1;;;;;;172697:20:0::3;172686:31:::0;::::3;172682:241;;;172746:20;:24:::0;;-1:-1:-1;;;;;;172746:24:0::3;::::0;;172682:241:::3;;;172858:20;:41:::0;;172890:8;;172858:20;::::3;::::0;:41:::3;::::0;172890:8;;-1:-1:-1;;;;;172858:41:0::3;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;172858:41:0::3;;;;;-1:-1:-1::0;;;;;172858:41:0::3;;;;;;172682:241;172580:362;172537:405;-1:-1:-1::0;;;173039:15:0::3;::::0;;;:6:::3;:15;::::0;;;;:32;;-1:-1:-1;;;;;173039:32:0;;::::3;-1:-1:-1::0;;;173039:32:0::3;::::0;::::3;;::::0;;-1:-1:-1;173090:26:0::3;:52:::0;;::::3;173126:15;173090:52;-1:-1:-1::0;;;173090:52:0::3;-1:-1:-1::0;;173090:52:0;;::::3;;::::0;;171232:1926:::3;170214:2955;;;;;;170151:3018;190659:9:::4;190639:16;190647:7:::0;190639::::4;:16::i;:::-;-1:-1:-1::0;;;;;190639:29:0::4;;190635:106;;190705:10;190685:16;190693:7:::0;190685::::4;:16::i;:::-;-1:-1:-1::0;;;;;190685:30:0::4;;190681:58;;190724:15;;-1:-1:-1::0;;;190724:15:0::4;;;;;;;;;;;190681:58;190755:16;-1:-1:-1::0;;;;;190755:21:0::4;190775:1;190755:21:::0;190751:49:::4;;190785:15;;-1:-1:-1::0;;;190785:15:0::4;;;;;;;;;;;190751:49;190870:25;190898:15:::0;;;:6:::4;:15;::::0;;;;190928:11;;190898:15;;-1:-1:-1;;;;;190928:11:0;;::::4;:16:::0;;190924:44:::4;;190953:15;;-1:-1:-1::0;;;190953:15:0::4;;;;;;;;;;;190924:44;191010:12;::::0;::::4;::::0;::::4;::::0;;::::4;190990:15;190983:39:::0;;::::4;;190979:65;;191031:13;;-1:-1:-1::0;;;191031:13:0::4;;;;;;;;;;;190979:65;191117:12;::::0;:37:::4;::::0;-1:-1:-1;;;191117:37:0;;191093:21:::4;::::0;-1:-1:-1;;;;;191117:12:0::4;::::0;:22:::4;::::0;:37:::4;::::0;191148:4:::4;::::0;191117:37:::4;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;191165:12;::::0;191093:61;;-1:-1:-1;191165:74:0::4;::::0;-1:-1:-1;;;;;191165:12:0::4;191195:10;191215:4;-1:-1:-1::0;;;;;191165:74:0;::::4;:29;:74::i;:::-;191295:32;-1:-1:-1::0;;;;;191295:32:0;::::4;:13:::0;:32:::4;:::i;:::-;191254:12;::::0;:37:::4;::::0;-1:-1:-1;;;191254:37:0;;-1:-1:-1;;;;;191254:12:0;;::::4;::::0;:22:::4;::::0;:37:::4;::::0;191285:4:::4;::::0;191254:37:::4;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:73;191250:115;;191349:16;;-1:-1:-1::0;;;191349:16:0::4;;;;;;;;;;;191250:115;191447:62;191468:7;191477:16;191495:13;191447:20;:62::i;:::-;190594:923;;170087:3101:::3;170035:1;158791::::2;156270:20:::0;155487:1;156790:7;:22;156607:213;201363:172;162602:13;:11;:13::i;:::-;201424:14:::1;:21:::0;;-1:-1:-1;;;;201424:21:0::1;-1:-1:-1::0;;;201424:21:0::1;::::0;;201456:8:::1;:6;:8::i;:::-;201501:25;::::0;201480:47:::1;::::0;::::1;::::0;::::1;::::0;-1:-1:-1;;;;;201501:25:0;;::::1;::::0;201480:47:::1;:::i;:::-;;;;;;;;201363:172::o:0;206080:2151::-;162602:13;:11;:13::i;:::-;206228:33;;::::1;206220:70;;;::::0;-1:-1:-1;;;206220:70:0;;17555:2:1;206220:70:0::1;::::0;::::1;17537:21:1::0;17594:2;17574:18;;;17567:30;-1:-1:-1;;;17613:18:1;;;17606:54;17677:18;;206220:70:0::1;17353:348:1::0;206220:70:0::1;206316:9;206311:1873;206331:19:::0;;::::1;206311:1873;;;206368:15;206386:8;;206395:1;206386:11;;;;;;;:::i;:::-;;;;;;;206368:29;;206445:1;-1:-1:-1::0;;;;;206416:31:0::1;:17;206425:7;206416:8;:17::i;:::-;-1:-1:-1::0;;;;;206416:31:0::1;::::0;206412:116:::1;;-1:-1:-1::0;206480:3:0::1;;206311:1873;;206412:116;206544:24;206571:15:::0;;;:6:::1;:15;::::0;;;;;;;;206544:42;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;206544:42:0;;::::1;::::0;;;-1:-1:-1;;;206544:42:0;;::::1;;::::0;;::::1;::::0;;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;206544:42:0;::::1;::::0;;::::1;::::0;;;;206605:15;206601:1540:::1;;206641:24;206668:7;;206676:1;206668:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;206641:37:::0;-1:-1:-1;;;;;;206701:20:0;::::1;::::0;206697:1429:::1;;206746:18;206767:29;206788:7;206767:20;:29::i;:::-;206856:11:::0;;206746:50;;-1:-1:-1;206819:25:0::1;::::0;166751:4:::1;::::0;206848:33:::1;::::0;-1:-1:-1;;;;;206848:33:0;;::::1;::::0;:20:::1;:33;:::i;:::-;206847:47;;;;:::i;:::-;206819:75;;206917:25;166751:4;-1:-1:-1::0;;;;;206945:66:0::1;206988:10;-1:-1:-1::0;;;;;206946:52:0::1;206968:16;206954:4;:11;;;:30;;;;:::i;:::-;-1:-1:-1::0;;;;;206946:39:0::1;:52;;;;:::i;:::-;206945:66;;;;:::i;:::-;207080:20;::::0;206917:94;;-1:-1:-1;;;;;;207080:20:0::1;207060:40:::0;::::1;207056:228;;;207129:20;:24:::0;;-1:-1:-1;;;;;;207129:24:0::1;::::0;;207056:228:::1;;;207210:20;:50:::0;;207242:17;;207210:20;::::1;::::0;:50:::1;::::0;207242:17;;-1:-1:-1;;;;;207210:50:0::1;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;207210:50:0::1;;;;;-1:-1:-1::0;;;;;207210:50:0::1;;;;;;207056:228;207306:20;:50:::0;;207338:17;;207306:20;::::1;::::0;:50:::1;::::0;207338:17;;-1:-1:-1;;;;;207306:50:0::1;;:::i;:::-;::::0;;::::1;::::0;;;::::1;-1:-1:-1::0;;;;;207306:50:0;;::::1;;::::0;;::::1;::::0;;::::1;;;::::0;;;-1:-1:-1;207401:15:0;;;:6:::1;:15;::::0;;;;:42;;207427:16;;-1:-1:-1;207401:15:0;;:42:::1;::::0;207427:16;;207401:42:::1;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;207401:42:0::1;;;;;-1:-1:-1::0;;;;;207401:42:0::1;;;;;;166545:8;207498:63;;166751:4;-1:-1:-1::0;;;;;207499:51:0::1;207521:16;207507:4;:11;;;:30;;;;:::i;:::-;-1:-1:-1::0;;;;;207499:39:0::1;:51;;;;:::i;:::-;207498:63;;;;:::i;:::-;207466:15;::::0;;;:6:::1;:15;::::0;;;;;;;;:96;;-1:-1:-1;;;;;207466:96:0;;::::1;-1:-1:-1::0;;;207466:96:0::1;::::0;::::1;::::0;;;::::1;::::0;;;207654:72;;;;::::1;::::0;;207692:11;;207654:72:::1;;::::0;;207712:12;;::::1;::::0;207654:72:::1;;::::0;;::::1;::::0;;;;207753:91;;;;::::1;::::0;;;207791:11;;207607:260:::1;::::0;207473:7;;207654:72;;207753:91;;207791:30:::1;::::0;207805:16;;207791:30:::1;:::i;:::-;207753:91;;;;;;207830:4;:12;;;207753:91;;;;::::0;207607:11:::1;:260::i;:::-;208052:12;::::0;208016::::1;::::0;207990:94:::1;::::0;-1:-1:-1;;;;;208016:12:0;;::::1;::::0;208052::::1;-1:-1:-1::0;;;;;207990:94:0;::::1;:53;:94::i;:::-;206723:1403;;;206697:1429;206622:1519;206601:1540;-1:-1:-1::0;;208167:3:0::1;;206311:1873;;;;208204:19;:17;:19::i;203412:495::-:0;203485:13;203540:1;203511:17;203520:7;203511:8;:17::i;:::-;-1:-1:-1;;;;;203511:31:0;;203507:60;;203551:16;;-1:-1:-1;;;203551:16:0;;;;;;;;;;;203507:60;203578:8;;-1:-1:-1;;;;;203578:8:0;203574:52;;203609:17;;-1:-1:-1;;;203609:17:0;;;;;;;;;;;203574:52;203719:8;;203749:53;;;;;7801:25:1;;;203684:12:0;;;;-1:-1:-1;;;;;203719:8:0;;;;7774:18:1;;203749:53:0;;;-1:-1:-1;;203749:53:0;;;;;;;;;;;;;;-1:-1:-1;;;;;203749:53:0;-1:-1:-1;;;203749:53:0;;;203719:90;;;203749:53;203719:90;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;203683:126;;;;203824:7;203816:41;;;;-1:-1:-1;;;203816:41:0;;18405:2:1;203816:41:0;;;18387:21:1;18444:2;18424:18;;;18417:30;-1:-1:-1;;;18463:18:1;;;18456:51;18524:18;;203816:41:0;18203:345:1;203816:41:0;203888:4;203877:26;;;;;;;;;;;;:::i;:::-;203870:33;203412:495;-1:-1:-1;;;;203412:495:0:o;208388:423::-;208442:7;;;208574:191;208598:12;;-1:-1:-1;;;208598:12:0;;;;208594:16;;208574:191;;;208659:1;208636:11;208645:1;208636:8;:11::i;:::-;-1:-1:-1;;;;;208636:25:0;;208632:122;;208722:9;;;;:6;:9;;;;;:16;208707:31;;-1:-1:-1;;;;;208722:16:0;208707:31;;:::i;:::-;;;208632:122;208612:3;;208574:191;;;-1:-1:-1;208792:11:0;208388:423;-1:-1:-1;208388:423:0:o;200675:368::-;200760:7;200784:13;;;;;:35;;-1:-1:-1;166545:8:0;200801:18;;;;200784:35;200780:65;;;200828:17;;-1:-1:-1;;;200828:17:0;;;;;;;;;;;200780:65;200860:6;-1:-1:-1;;;;;200860:11:0;200870:1;200860:11;200856:39;;200880:15;;-1:-1:-1;;;200880:15:0;;;;;;;;;;;200856:39;200916:13;166751:4;200941:25;166545:8;-1:-1:-1;;;;;200941:15:0;;:25;:::i;:::-;200940:39;;;;:::i;:::-;200916:64;;200998:37;201019:5;201026:8;200998:20;:37::i;198807:1858::-;198888:7;198967:15;;;:6;:15;;;;;;;;198940:42;;;;;;;;;-1:-1:-1;;;;;198940:42:0;;;;;;-1:-1:-1;;;198940:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;198940:42:0;;;;;;;;;;198997:16;;198993:30;;199022:1;199015:8;;;;;198993:30;199130:4;:12;;;199117:25;;:9;:25;;;199113:49;;199151:11;;-1:-1:-1;199144:18:0;;199113:49;199258:4;:15;;;199246:27;;:9;:27;;;199242:41;;;199282:1;199275:8;;;;;199242:41;199386:12;;;;199357:17;;166545:8;;166751:4;;199386:24;;199401:9;;199386:24;:::i;:::-;199378:33;;:45;;;;:::i;:::-;199377:57;;;;:::i;:::-;199357:77;-1:-1:-1;199445:18:0;166751:4;199499:32;166751:4;166649;199499:32;:::i;:::-;199486:46;;-1:-1:-1;;;;;199486:46:0;:9;:46;:::i;:::-;199485:60;;;;:::i;:::-;199466:80;;166703:4;199466:80;:::i;:::-;199445:101;-1:-1:-1;166649:4:0;199570:27;;:127;;166703:4;199638:28;;:59;;199687:10;199570:127;;199638:59;166703:4;199570:127;;;166649:4;199570:127;199776:11;;199557:140;;-1:-1:-1;199751:13:0;;166751:4;;199768:33;;199557:140;;-1:-1:-1;;;;;199768:20:0;:33;:::i;:::-;199767:47;;;;:::i;:::-;199751:63;-1:-1:-1;;;;;;199829:25:0;;199825:55;;;-1:-1:-1;;;;;199856:24:0;;;;;;;;199825:55;199928:16;199947:23;;;:14;:23;;;;;;;;;200051:510;200083:1;200078;:6;;;200051:510;;200106:18;200127:25;;;:16;:25;;;;;;;;:28;;;;;;;;;;;;;200106:49;;;;;;;;;;;;;;;-1:-1:-1;;;200106:49:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;200106:49:0;;;;;;;;;;200174:21;;-1:-1:-1;200170:380:0;;200297:10;;:15;;;:34;;;;-1:-1:-1;200316:11:0;;-1:-1:-1;;;;;200316:15:0;;;200297:34;200293:104;;;200371:5;200356:21;;;;;;;;;;;200293:104;200521:10;-1:-1:-1;;;;;200505:28:0;;-1:-1:-1;200490:44:0;;-1:-1:-1;;;;;;200490:44:0;200170:380;-1:-1:-1;200086:3:0;;;;:::i;:::-;;;;200051:510;;;-1:-1:-1;200651:5:0;;198807:1858;-1:-1:-1;;;;;;;198807:1858:0:o;201056:271::-;201196:15;;201140:7;;;;201196:15;-1:-1:-1;;;201196:15:0;;;;;201181:30;;;;:78;;201247:12;201181:78;;;201229:15;;201214:30;;-1:-1:-1;;;201229:15:0;;;;201214:12;:30;:::i;:::-;201160:99;;201277:42;201299:6;201307:11;201277:21;:42::i;184867:390::-;185064:15;158761:19;:17;:19::i;:::-;185045:8:::1;169990;169972:15;:26;169968:56;;;170007:17;;-1:-1:-1::0;;;170007:17:0::1;;;;;;;;;;;169968:56;185101:148:::2;185129:10;185154:6;185175:12;185202:8;185225:13;185101;:148::i;117526:213::-:0;117614:4;117631:23;117657:19;:17;:19::i;:::-;-1:-1:-1;;;;;117694:27:0;;;;;;;:20;;;;;:27;;;;;;;;:37;;;;;;;;;;-1:-1:-1;;117694:37:0;;;;;117526:213::o;163709:220::-;162602:13;:11;:13::i;:::-;-1:-1:-1;;;;;163794:22:0;::::1;163790:93;;163868:1;163840:31;;-1:-1:-1::0;;;163840:31:0::1;;;;;;;;:::i;163790:93::-;163893:28;163912:8;163893:18;:28::i;202136:68::-:0;162602:13;:11;:13::i;:::-;202186:10:::1;:8;:10::i;114153:160::-:0;114274:21;;114153:160::o;130540:247::-;130603:7;130623:13;130639:17;130648:7;130639:8;:17::i;:::-;130623:33;-1:-1:-1;;;;;;130671:19:0;;130667:90;;130714:31;;-1:-1:-1;;;130714:31:0;;;;;7801:25:1;;;7774:18;;130714:31:0;7655:177:1;119727:187:0;119797:7;119817:23;119843:19;:17;:19::i;:::-;119880:26;;;;:17;;:26;;-1:-1:-1;;119880:26:0;;;;-1:-1:-1;;;;;119880:26:0;;119727:187::o;128656:122::-;128737:33;128746:2;128750:7;128759:4;128765;128737:8;:33::i;119431:175::-;119497:7;119517:23;119543:19;:17;:19::i;:::-;119580:18;;;;:9;;:18;;-1:-1:-1;;119580:18:0;;;;-1:-1:-1;;;;;119580:18:0;;119431:175::o;156306:293::-;155531:1;156440:7;;:19;156432:63;;;;-1:-1:-1;;;156432:63:0;;19637:2:1;156432:63:0;;;19619:21:1;19676:2;19656:18;;;19649:30;19715:33;19695:18;;;19688:61;19766:18;;156432:63:0;19435:355:1;156432:63:0;155531:1;156573:7;:18;156306:293::o;159315:108::-;159227:7;;;;159385:9;159377:38;;;;-1:-1:-1;;;159377:38:0;;19997:2:1;159377:38:0;;;19979:21:1;20036:2;20016:18;;;20009:30;-1:-1:-1;;;20055:18:1;;;20048:46;20111:18;;159377:38:0;19795:340:1;187305:380:0;187371:7;;187465:25;166545:8;-1:-1:-1;;;;;187465:15:0;;:25;:::i;:::-;187445:45;-1:-1:-1;187552:21:0;166751:4;187445:45;187552:21;:::i;:::-;187540:33;-1:-1:-1;;;;;;187592:30:0;;;187584:57;;;;-1:-1:-1;;;187584:57:0;;20342:2:1;187584:57:0;;;20324:21:1;20381:2;20361:18;;;20354:30;-1:-1:-1;;;20400:18:1;;;20393:44;20454:18;;187584:57:0;20140:338:1;187693:758:0;187778:7;187892:5;-1:-1:-1;;;;;187892:10:0;187901:1;187892:10;187888:38;;-1:-1:-1;166703:4:0;187904:22;;187888:38;188004:17;166545:8;188025:29;166751:4;188024:41;188025:17;;:29;:::i;:::-;188024:41;;;;:::i;:::-;188004:61;-1:-1:-1;188139:18:0;166751:4;188207:32;166751:4;166649;188207:32;:::i;:::-;188194:46;;-1:-1:-1;;;;;188194:46:0;:9;:46;:::i;:::-;188193:60;;;;:::i;:::-;188160:94;;166703:4;188160:94;:::i;:::-;188139:115;-1:-1:-1;166649:4:0;188279:27;;188275:54;;;166649:4;188308:21;;;;;;188275:54;166703:4;188344:28;;188340:56;;;166703:4;188374:22;;;;;;182649:2210;182832:24;182859:15;;;:6;:15;;;;;;;;182832:42;;;;;;;;;-1:-1:-1;;;;;182832:42:0;;;;;-1:-1:-1;;;182832:42:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;182832:42:0;;;;;;;;;;;:24;183038:15;183016:38;-1:-1:-1;183012:857:0;;;183071:15;183111;183089:4;:12;;;:38;;;;:::i;:::-;183071:56;-1:-1:-1;183203:17:0;166545:8;183224:29;166751:4;183223:41;183224:17;;:29;:::i;:::-;183223:41;;;;:::i;:::-;183203:61;-1:-1:-1;183350:22:0;166751:4;183426:32;166751:4;166649;183426:32;:::i;:::-;183413:46;;-1:-1:-1;;;;;183413:46:0;:9;:46;:::i;:::-;183412:60;;;;:::i;:::-;183375:98;;166703:4;183375:98;:::i;:::-;183350:123;-1:-1:-1;166649:4:0;183506:31;;183502:292;;;166649:4;183558:30;;183502:292;;;166703:4;183614:32;;183610:184;;;166703:4;183667:31;;183610:184;;;183763:14;183739:39;;183610:184;183056:749;;;183012:857;;;-1:-1:-1;166703:4:0;183012:857;183940:25;166751:4;183969:40;-1:-1:-1;;;;;183987:22:0;;;;183969:15;;:40;:::i;:::-;183968:54;;;;:::i;:::-;183940:82;-1:-1:-1;184033:25:0;166751:4;184062:40;-1:-1:-1;;;;;184080:22:0;;;;184062:15;;:40;:::i;:::-;184061:54;;;;:::i;:::-;184033:82;;184227:17;184207;:37;184203:610;;;184261:16;184280:37;184300:17;184280;:37;:::i;:::-;184261:56;-1:-1:-1;;;;;;184336:28:0;;184332:58;;;184373:17;;-1:-1:-1;;;184373:17:0;;;;;;;;;;;184332:58;184405:20;:41;;184437:8;;184405:20;;;:41;;184437:8;;-1:-1:-1;;;;;184405:41:0;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;184405:41:0;;;;;-1:-1:-1;;;;;184405:41:0;;;;;;184246:212;184203:610;;;184488:17;184468;:37;184464:349;;;184522:16;184541:37;184561:17;184541;:37;:::i;:::-;184608:20;;184522:56;;-1:-1:-1;;;;;;184608:20:0;184597:31;;184593:209;;;184649:20;:24;;-1:-1:-1;;;;;;184649:24:0;;;184593:209;;;184745:20;:41;;184777:8;;184745:20;;;:41;;184777:8;;-1:-1:-1;;;;;184745:41:0;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;184745:41:0;;;;;-1:-1:-1;;;;;184745:41:0;;;;;;184593:209;184507:306;184464:349;182745:2114;;;;182649:2210;;;:::o;174283:363::-;174439:19;:17;:19::i;:::-;174483:12;;174479:160;;174512:115;174547:7;174574:9;174603;174512:16;:115::i;156607:213::-;155487:1;156790:7;:22;156607:213::o;114437:151::-;22574:20;:18;:20::i;:::-;114541:39:::1;114565:5;114572:7;114541:23;:39::i;155573:113::-:0;22574:20;:18;:20::i;:::-;155644:34:::1;:32;:34::i;158326:99::-:0;22574:20;:18;:20::i;:::-;158390:27:::1;:25;:27::i;162100:129::-:0;22574:20;:18;:20::i;:::-;162183:38:::1;162208:12;162183:24;:38::i;159752:118::-:0;158761:19;:17;:19::i;:::-;159812:7:::1;:14:::0;;-1:-1:-1;;159812:14:0::1;159822:4;159812:14;::::0;;159842:20:::1;159849:12;25439:10:::0;;25359:98;159849:12:::1;159842:20;;;;;;:::i;117806:588::-:0;-1:-1:-1;;;;;117901:16:0;;117897:89;;117971:1;117941:33;;-1:-1:-1;;;117941:33:0;;;;;;;;:::i;117897:89::-;118207:21;118231:34;118239:2;118243:7;25439:10;118231:7;:34::i;:::-;118207:58;;118297:4;-1:-1:-1;;;;;118280:21:0;:13;-1:-1:-1;;;;;118280:21:0;;118276:111;;118325:50;;-1:-1:-1;;;118325:50:0;;-1:-1:-1;;;;;20703:32:1;;;118325:50:0;;;20685:51:1;20752:18;;;20745:34;;;20815:32;;20795:18;;;20788:60;20658:18;;118325:50:0;20483:371:1;181738:748:0;181889:13;;;182009:25;166545:8;-1:-1:-1;;;;;182009:15:0;;:25;:::i;:::-;181989:45;-1:-1:-1;182096:21:0;166751:4;181989:45;182096:21;:::i;:::-;182084:33;-1:-1:-1;;;;;;182136:30:0;;;182128:57;;;;-1:-1:-1;;;182128:57:0;;21061:2:1;182128:57:0;;;21043:21:1;21100:2;21080:18;;;21073:30;-1:-1:-1;;;21119:18:1;;;21112:44;21173:18;;182128:57:0;20859:338:1;182128:57:0;182212:9;182196:26;;182289:41;182310:5;182317:12;182289:20;:41::i;:::-;182276:54;-1:-1:-1;166649:4:0;-1:-1:-1;;;;;182355:27:0;;;182351:59;;;182391:19;;-1:-1:-1;;;182391:19:0;;;;;;;;;;;182351:59;182438:13;-1:-1:-1;;;;;182425:26:0;:10;-1:-1:-1;;;;;182425:26:0;;182421:57;;;182460:18;;-1:-1:-1;;;182460:18:0;;;;;;;;;;;182421:57;181924:562;181738:748;;;;;;:::o;148027:216::-;148166:68;;-1:-1:-1;;;;;21422:32:1;;;148166:68:0;;;21404:51:1;21491:32;;21471:18;;;21464:60;21540:18;;;21533:34;;;148139:96:0;;148159:5;;-1:-1:-1;;;148189:27:0;21377:18:1;;148166:68:0;;;;-1:-1:-1;;148166:68:0;;;;;;;;;;;;;;-1:-1:-1;;;;;148166:68:0;-1:-1:-1;;;;;;148166:68:0;;;;;;;;;;148139:19;:96::i;124724:102::-;124792:26;124802:2;124806:7;124792:26;;;;;;;;;;;;:9;:26::i;147594:188::-;147715:58;;-1:-1:-1;;;;;21770:32:1;;147715:58:0;;;21752:51:1;21819:18;;;21812:34;;;147688:86:0;;147708:5;;-1:-1:-1;;;147738:23:0;21725:18:1;;147715:58:0;21578:274:1;125602:232:0;125654:21;125678:40;125694:1;125698:7;125715:1;125678:7;:40::i;:::-;125654:64;-1:-1:-1;;;;;;125733:27:0;;125729:98;;125784:31;;-1:-1:-1;;;125784:31:0;;;;;7801:25:1;;;7774:18;;125784:31:0;7655:177:1;162941:166:0;25439:10;163001:7;:5;:7::i;:::-;-1:-1:-1;;;;;163001:23:0;;162997:103;;25439:10;163048:40;;-1:-1:-1;;;163048:40:0;;;;;;;;:::i;164089:253::-;161547:22;164240:8;;-1:-1:-1;;;;;;164259:19:0;;-1:-1:-1;;;;;164259:19:0;;;;;;;;164294:40;;164240:8;;;;;164294:40;;164163:24;;164294:40;164152:190;;164089:253;:::o;191732:646::-;191804:7;191824:9;166591;;191837:5;:8;;;:15;;;;:::i;:::-;191836:24;;;;:::i;:::-;191824:36;-1:-1:-1;191886:9:0;191881:388;191905:3;191901:1;:7;191881:388;;;191926:10;166591:9;191926:10;;:::i;:::-;;;191960:1;191955:6;;:2;:6;;;191951:128;;;192029:8;;;;192025:12;;:1;:12;:::i;:::-;192017:21;;191996:5;:11;;;:43;;;;:::i;:::-;191982:57;;:5;;:57;;;;;:::i;:::-;;;;;-1:-1:-1;192058:5:0;;191951:128;192141:8;;;;192136:13;;:2;:13;:::i;:::-;192128:22;;192107:5;:11;;;:44;;;;:::i;:::-;192093:58;;:5;;:58;;;;;:::i;:::-;;;;;;;;192181:16;;;;;;;:12;:16;;;;;;;;;192166:11;;;:31;;192181:16;;;;;-1:-1:-1;192166:31:0;;192181:16;;192166:31;:::i;:::-;;;;;-1:-1:-1;192212:13:0;;;:8;;;:13;192252:3;;191881:388;;;;192298:1;192285:5;:10;;;:14;;;192281:34;;;192314:1;192301:14;;192281:34;-1:-1:-1;;192357:10:0;;-1:-1:-1;;;;;192341:28:0;;191732:646;-1:-1:-1;191732:646:0:o;129921:376::-;130025:23;130051:19;:17;:19::i;:::-;130025:45;-1:-1:-1;;;;;;130085:22:0;;130081:93;;130153:8;130131:31;;-1:-1:-1;;;130131:31:0;;;;;;;;:::i;130081:93::-;-1:-1:-1;;;;;130184:27:0;;;;;;;:20;;;:27;;;;;;;;:37;;;;;;;;;;;;;:48;;-1:-1:-1;;130184:48:0;;;;;;;;;;130248:41;;540::1;;;130248::0;;513:18:1;130248:41:0;;;;;;;130014:283;129921:376;;;:::o;118670:236::-;118784:31;118797:4;118803:2;118807:7;118784:12;:31::i;:::-;118826:72;25439:10;118874:4;118880:2;118884:7;118893:4;118826:33;:72::i;188516:1841::-;188665:25;188693:15;;;:6;:15;;;;;188801:11;;188693:15;;-1:-1:-1;;;;;188801:11:0;;;;188843:28;188855:16;188801:11;188843:28;:::i;:::-;188899:12;;;;188823:48;;-1:-1:-1;188899:12:0;;188882:14;188949:33;188966:15;188899:12;188949:33;:::i;:::-;188922:60;;189050:16;189069:29;189088:9;189069:18;:29::i;:::-;189050:48;;189109:18;189130:49;189151:8;189161:17;189130:20;:49::i;:::-;189109:70;;189256:25;189284:29;189305:7;189284:20;:29::i;:::-;189256:57;;189350:17;-1:-1:-1;;;;;189337:30:0;:10;-1:-1:-1;;;;;189337:30:0;;:63;;189383:17;189337:63;;;189370:10;189337:63;189324:76;-1:-1:-1;189492:16:0;189504:4;166751;189492:16;:::i;:::-;-1:-1:-1;;;;;189473:35:0;:16;-1:-1:-1;;;;;189473:35:0;;:65;;;;;189525:13;-1:-1:-1;;;;;189512:26:0;:10;-1:-1:-1;;;;;189512:26:0;;189473:65;189469:123;;;189562:18;;-1:-1:-1;;;189562:18:0;;;;;;;;;;;189469:123;189670:302;189696:7;189718:114;;;;;;;;189774:9;189718:114;;;;;;189809:7;189718:114;;;;;189847;;;;;;;;189903:9;189847:114;;;;;;189938:7;189847:114;;;;;189670:11;:302::i;:::-;-1:-1:-1;;;;;190057:21:0;;;-1:-1:-1;;;190057:21:0;190023:23;;;190057:21;;;190023:23;190089:15;;:41;;;190114:15;190089:41;-1:-1:-1;;;190089:41:0;-1:-1:-1;;190089:41:0;;;;;;190186:60;190208:7;190217:16;190235:10;190186:21;:60::i;:::-;190272:77;;;-1:-1:-1;;;;;23401:32:1;;;23383:51;;23470:32;;;23465:2;23450:18;;23443:60;23539:32;;23519:18;;;23512:60;190272:77:0;;190300:7;;190288:10;;190272:77;;;;;23371:2:1;190272:77:0;;;188654:1703;;;;;;;;188516:1841;;;:::o;174654:1236::-;174719:5;;;;174735:22;;:::i;:::-;174813:10;;;;174809:289;;174852:12;:24;174865:10;174874:1;174865:6;:10;:::i;:::-;174852:24;;;;;;;;;;;;;;;;;;-1:-1:-1;174852:24:0;174840:36;;;;;;;;;;;;;;;-1:-1:-1;;;174840:36:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;174840:36:0;;;;;;;;;-1:-1:-1;174809:289:0;;;-1:-1:-1;174921:165:0;;;;;;;;-1:-1:-1;174921:165:0;;;;;;;;175010:15;174921:165;;;;;;;;;175057:12;174921:165;;;;;;;174809:289;175134:12;;;;175110:21;175261:40;;;;175268:15;175261:40;;;;175257:198;;;175429:12;;;;175411:30;;;;:15;:30;:::i;:::-;175368:13;;;;175353:28;;;;:12;:28;:::i;:::-;175340:42;;166751:4;175340:42;:::i;:::-;175339:103;;;;:::i;:::-;175318:125;;175257:198;175518:135;175558:9;175582:14;175611:10;175636:6;175518:25;:135::i;:::-;175506:147;-1:-1:-1;175674:10:0;:6;175683:1;175674:10;:::i;:::-;175666:5;:18;;;;;;-1:-1:-1;;175666:18:0;;;;;;175695:20;;;175666:5;175695:20;;;:12;:20;;;;;;;;:32;;;;;;-1:-1:-1;;;;;175695:32:0;;;-1:-1:-1;;;175695:32:0;;;;;;;;;;;175666:18;175695:32;;;;;;;;;;;;-1:-1:-1;;;175695:32:0;-1:-1:-1;;;;;;175695:32:0;;;;;;;;;;;;;;;;;;;;;;;175818:18;175814:69;;;-1:-1:-1;;175870:1:0;175853:18;;-1:-1:-1;174654:1236:0:o;160011:120::-;159020:16;:14;:16::i;:::-;160070:7:::1;:15:::0;;-1:-1:-1;;160070:15:0::1;::::0;;160101:22:::1;25439:10:::0;160110:12:::1;25359:98:::0;128966:736;129071:23;129097:19;:17;:19::i;:::-;129071:45;;129184:9;:31;;;-1:-1:-1;;;;;;129197:18:0;;;;129184:31;129180:471;;;129232:13;129248:22;129262:7;129248:13;:22::i;:::-;129232:38;-1:-1:-1;;;;;;129401:18:0;;;;;;:35;;;129432:4;-1:-1:-1;;;;;129423:13:0;:5;-1:-1:-1;;;;;129423:13:0;;;129401:35;:69;;;;;129441:29;129458:5;129465:4;129441:16;:29::i;:::-;129440:30;129401:69;129397:144;;;129520:4;129498:27;;-1:-1:-1;;;129498:27:0;;;;;;;;:::i;129397:144::-;129561:9;129557:83;;;129616:7;129612:2;-1:-1:-1;;;;;129596:28:0;129605:5;-1:-1:-1;;;;;129596:28:0;;;;;;;;;;;129557:83;129217:434;129180:471;129663:26;;;;:17;;:26;;-1:-1:-1;;129663:26:0;;;:31;;-1:-1:-1;;;;;;129663:31:0;-1:-1:-1;;;;;129663:31:0;;;;;;;;;;128966:736::o;176986:650::-;177147:17;;:::i;:::-;177175;;:::i;:::-;177212:34;177230:9;177241:4;177212:17;:34::i;:::-;;177257;177275:9;177286:4;177257:17;:34::i;:::-;;177312:71;177338:9;177349;177360:4;:10;;;177372:4;:10;;;177312:25;:71::i;:::-;177396:16;177415:23;;;:14;:23;;;;;;:27;;:23;;;:27;:::i;:::-;177453:23;;;;:14;:23;;;;;;;;:35;;;;;;-1:-1:-1;;177453:35:0;;;;;;;;177516:15;177499:33;;:7;;;:33;;;177561:12;177543:31;;:8;;;:31;;;177585:25;;;:16;:25;;;;;:36;;;;;;;;:43;;;;;;;-1:-1:-1;;;;;177585:43:0;;;-1:-1:-1;;;177585:43:0;;;;;;;;;;177453:35;177585:43;;;;;;;;;;-1:-1:-1;;;177585:43:0;-1:-1:-1;;;;;;177585:43:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;;176986:650:0:o;22734:145::-;24567:21;24248:40;-1:-1:-1;;;24248:40:0;;;;22797:75;;22843:17;;-1:-1:-1;;;22843:17:0;;;;;;;;;;;114596:223;22574:20;:18;:20::i;:::-;114710:23:::1;114736:19;:17;:19::i;:::-;114710:45:::0;-1:-1:-1;114710:45:0;114766:15:::1;114776:5:::0;114710:45;114766:15:::1;:::i;:::-;-1:-1:-1::0;114792:9:0::1;::::0;::::1;:19;114804:7:::0;114792:9;:19:::1;:::i;155694:111::-:0;22574:20;:18;:20::i;158433:97::-;22574:20;:18;:20::i;:::-;158507:7:::1;:15:::0;;-1:-1:-1;;158507:15:0::1;::::0;;158433:97::o;162237:240::-;22574:20;:18;:20::i;122804:886::-;122890:7;122910:23;122936:19;:17;:19::i;:::-;122910:45;;122966:12;122981:17;122990:7;122981:8;:17::i;:::-;122966:32;-1:-1:-1;;;;;;123061:18:0;;;123057:88;;123096:37;123113:4;123119;123125:7;123096:16;:37::i;:::-;-1:-1:-1;;;;;123192:18:0;;;123188:265;;123310:48;123327:1;123331:7;123348:1;123352:5;123310:8;:48::i;:::-;-1:-1:-1;;;;;123404:17:0;;;;;;:11;;;:17;;;;;:22;;-1:-1:-1;;123404:22:0;;;123188:265;-1:-1:-1;;;;;123469:16:0;;;123465:113;;-1:-1:-1;;;;;123531:15:0;;;;;;:11;;;:15;;;;;:20;;123550:1;123531:20;;;123465:113;123590:18;;;;:9;;;:18;;;;;;:23;;-1:-1:-1;;;;;;123590:23:0;-1:-1:-1;;;;;123590:23:0;;;;;;;;;123631:27;;123590:18;;123631:27;;;;;;;123678:4;122804:886;-1:-1:-1;;;;;122804:886:0:o;152017:660::-;152452:23;152478:69;152506:4;152478:69;;;;;;;;;;;;;;;;;152486:5;-1:-1:-1;;;;;152478:27:0;;;:69;;;;;:::i;:::-;152452:95;;152566:10;:17;152587:1;152566:22;:56;;;;152603:10;152592:30;;;;;;;;;;;;:::i;:::-;152558:111;;;;-1:-1:-1;;;152558:111:0;;26159:2:1;152558:111:0;;;26141:21:1;26198:2;26178:18;;;26171:30;26237:34;26217:18;;;26210:62;-1:-1:-1;;;26288:18:1;;;26281:40;26338:19;;152558:111:0;25957:406:1;125053:210:0;125148:18;125154:2;125158:7;125148:5;:18::i;:::-;125177:78;25439:10;125233:1;125237:2;125241:7;125250:4;14630:948;-1:-1:-1;;;;;14817:14:0;;;:18;14813:758;;14856:67;;-1:-1:-1;;;14856:67:0;;-1:-1:-1;;;;;14856:36:0;;;;;:67;;14893:8;;14903:4;;14909:7;;14918:4;;14856:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;14856:67:0;;;;;;;;-1:-1:-1;;14856:67:0;;;;;;;;;;;;:::i;:::-;;;14852:708;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15219:6;:13;15236:1;15219:18;15215:330;;15361:2;15325:39;;-1:-1:-1;;;15325:39:0;;;;;;;;:::i;15215:330::-;15495:6;15489:13;15480:6;15476:2;15472:15;15465:38;14852:708;-1:-1:-1;;;;;;14971:51:0;;-1:-1:-1;;;14971:51:0;14967:185;;15129:2;15093:39;;-1:-1:-1;;;15093:39:0;;;;;;;;:::i;14967:185::-;14924:243;14852:708;14630:948;;;;;:::o;175898:1080::-;176076:12;;:::i;:::-;176101:9;166591;176114:21;166591:9;176114:14;:21;:::i;:::-;176113:30;;;;:::i;:::-;176101:42;-1:-1:-1;176172:15:0;176154:8;176209:735;176233:3;176229:1;:7;176209:735;;;176254:10;166591:9;176254:10;;:::i;:::-;;;176288:1;176283:6;;:2;:6;;;176279:232;;;176361:18;176365:14;176361:1;:18;:::i;:::-;176353:27;;176328:9;:15;;;:53;;;;:::i;:::-;176310:71;;:9;;:71;;;;;:::i;:::-;;;;;-1:-1:-1;176400:16:0;;;;:12;;;:16;176458:12;176435:36;:13;;;:36;176490:5;;176279:232;176576:19;176581:14;176576:2;:19;:::i;:::-;176568:28;;176543:9;:15;;;:54;;;;:::i;:::-;176525:72;;:9;;:72;;;;;:::i;:::-;;;;;;;;176631:16;;;;;;;:12;:16;;;;;;;;;176612:15;;;:35;;176631:16;;;;;-1:-1:-1;176612:35:0;;176631:16;;176612:35;:::i;:::-;;;;;-1:-1:-1;176662:17:0;;;:12;;;:17;;;166751:4;;176757:17;;176677:2;176757:17;:::i;:::-;176734:41;;;;-1:-1:-1;;;;;176734:19:0;;:41;:::i;:::-;176733:55;;;;:::i;:::-;176717:9;:13;;;:71;;;;;;:::i;:::-;176694:95;;:13;;;:95;:9;176818:12;:36;176851:1;176831:10;:6;176840:1;176831:10;:::i;:::-;:22;;;;:::i;:::-;176818:36;;;;;;;;;;;;;;;;;;-1:-1:-1;176818:36:0;:48;;;;;;-1:-1:-1;;;;;176818:48:0;;;-1:-1:-1;;;176818:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;176818:48:0;-1:-1:-1;;;;;;176818:48:0;;;;;;;;;;;;;;;176898:2;;-1:-1:-1;176898:2:0;;176927:3;176209:735;;;-1:-1:-1;176961:9:0;;175898:1080;-1:-1:-1;;;;;;175898:1080:0:o;159500:108::-;159227:7;;;;159559:41;;;;-1:-1:-1;;;159559:41:0;;27314:2:1;159559:41:0;;;27296:21:1;27353:2;27333:18;;;27326:30;-1:-1:-1;;;27372:18:1;;;27365:50;27432:18;;159559:41:0;27112:344:1;177644:907:0;177768:4;177810:15;177789:37;;:6;:10;;;:37;;;;:59;;;-1:-1:-1;177830:13:0;;:18;;;177789:59;177785:77;;;-1:-1:-1;177857:5:0;177850:12;;177785:77;177883:16;177930:15;177910:6;:10;;;:36;;;;:::i;:::-;177902:45;;;-1:-1:-1;166545:8:0;177969:18;;:39;;178000:8;177969:39;;;166545:8;177969:39;177958:50;-1:-1:-1;178029:18:0;166545:8;178082:32;166703:4;166649;178082:32;:::i;:::-;178070:45;;-1:-1:-1;;;;;178070:45:0;:8;:45;:::i;:::-;178069:57;;;;:::i;:::-;178050:77;;166703:4;178050:77;:::i;:::-;178029:98;-1:-1:-1;166649:4:0;178151:27;;:127;;166703:4;178219:28;;:59;;178268:10;178151:127;;178219:59;166703:4;178151:127;;;166649:4;178151:127;178338:13;;178138:140;;-1:-1:-1;;;;;;178322:31:0;166751:4;178393:25;178138:140;178322:31;178393:25;:::i;:::-;178392:39;;;;:::i;:::-;178364:69;;;;166545:8;178474:24;166751:4;178474:12;:24;:::i;:::-;178473:36;;;;:::i;:::-;178444:67;;:11;;;:67;-1:-1:-1;178539:4:0;;-1:-1:-1;;;177644:907:0;;;;:::o;178559:1291::-;178824:15;178801:39;;:9;:13;;;:39;;;178797:579;;;178933:13;;;;;178920:27;;178901:16;178920:27;;;:12;:27;;;;;;;;;178962:21;178975:8;178920:27;178962:21;:::i;:::-;;;179171:9;:13;;;179154:30;;:9;:13;;;:30;;;179150:147;;179205:21;179218:8;179205:21;;:::i;:::-;;;179150:147;179338:13;;;;;179325:27;;;;;;:12;:27;;;;;;:39;;-1:-1:-1;;;;;;179325:39:0;-1:-1:-1;;;;;179325:39:0;;;;;;;;;;178797:579;179457:15;179434:39;;:9;:13;;;:39;;;179430:413;;;179510:9;:13;;;179494:29;;:9;:13;;;:29;;;179490:342;;;179655:13;;;;;179642:27;;179623:16;179642:27;;;:12;:27;;;;;;;;;179688:21;179701:8;179642:27;179688:21;:::i;:::-;179790:13;;;;;179777:27;;;;;;:12;:27;;;;;;:39;;-1:-1:-1;;;;;179777:39:0;;;-1:-1:-1;;;;;;179777:39:0;;;;;;;;;-1:-1:-1;178559:1291:0;;;;:::o;120953:376::-;121066:38;121080:5;121087:7;121096;121066:13;:38::i;:::-;121061:261;;-1:-1:-1;;;;;121125:19:0;;121121:190;;121172:31;;-1:-1:-1;;;121172:31:0;;;;;7801:25:1;;;7774:18;;121172:31:0;7655:177:1;121121:190:0;121251:44;;-1:-1:-1;;;121251:44:0;;-1:-1:-1;;;;;21770:32:1;;121251:44:0;;;21752:51:1;21819:18;;;21812:34;;;21725:18;;121251:44:0;21578:274:1;141417:229:0;141554:12;141586:52;141608:6;141616:4;141622:1;141625:12;141586:21;:52::i;124026:335::-;-1:-1:-1;;;;;124094:16:0;;124090:89;;124164:1;124134:33;;-1:-1:-1;;;124134:33:0;;;;;;;;:::i;124090:89::-;124189:21;124213:32;124221:2;124225:7;124242:1;124213:7;:32::i;:::-;124189:56;-1:-1:-1;;;;;;124260:27:0;;;124256:98;;124339:1;124311:31;;-1:-1:-1;;;124311:31:0;;;;;;;;:::i;120234:276::-;120337:4;-1:-1:-1;;;;;120374:21:0;;;;;;:128;;;120422:7;-1:-1:-1;;;;;120413:16:0;:5;-1:-1:-1;;;;;120413:16:0;;:52;;;;120433:32;120450:5;120457:7;120433:16;:32::i;:::-;120413:88;;;;120494:7;-1:-1:-1;;;;;120469:32:0;:21;120482:7;120469:12;:21::i;:::-;-1:-1:-1;;;;;120469:32:0;;;120234:276;-1:-1:-1;;;;120234:276:0:o;142503:455::-;142673:12;142731:5;142706:21;:30;;142698:81;;;;-1:-1:-1;;;142698:81:0;;27663:2:1;142698:81:0;;;27645:21:1;27702:2;27682:18;;;27675:30;27741:34;27721:18;;;27714:62;-1:-1:-1;;;27792:18:1;;;27785:36;27838:19;;142698:81:0;27461:402:1;142698:81:0;142791:12;142805:23;142832:6;-1:-1:-1;;;;;142832:11:0;142851:5;142858:4;142832:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;142790:73;;;;142881:69;142908:6;142916:7;142925:10;142937:12;142881:26;:69::i;:::-;142874:76;142503:455;-1:-1:-1;;;;;;;142503:455:0:o;145076:644::-;145261:12;145290:7;145286:427;;;145318:10;:17;145339:1;145318:22;145314:290;;-1:-1:-1;;;;;138957:19:0;;;145528:60;;;;-1:-1:-1;;;145528:60:0;;28070:2:1;145528:60:0;;;28052:21:1;28109:2;28089:18;;;28082:30;28148:31;28128:18;;;28121:59;28197:18;;145528:60:0;27868:353:1;145528:60:0;-1:-1:-1;145625:10:0;145618:17;;145286:427;145668:33;145676:10;145688:12;146423:17;;:21;146419:388;;146655:10;146649:17;146712:15;146699:10;146695:2;146691:19;146684:44;146419:388;146782:12;146775:20;;-1:-1:-1;;;146775:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:131:1:-;-1:-1:-1;;;;;;88:32:1;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;592:289::-;634:3;672:5;666:12;699:6;694:3;687:19;755:6;748:4;741:5;737:16;730:4;725:3;721:14;715:47;807:1;800:4;791:6;786:3;782:16;778:27;771:38;870:4;863:2;859:7;854:2;846:6;842:15;838:29;833:3;829:39;825:50;818:57;;;592:289;;;;:::o;886:220::-;1035:2;1024:9;1017:21;998:4;1055:45;1096:2;1085:9;1081:18;1073:6;1055:45;:::i;1111:226::-;1170:6;1223:2;1211:9;1202:7;1198:23;1194:32;1191:52;;;1239:1;1236;1229:12;1191:52;-1:-1:-1;1284:23:1;;1111:226;-1:-1:-1;1111:226:1:o;1342:203::-;-1:-1:-1;;;;;1506:32:1;;;;1488:51;;1476:2;1461:18;;1342:203::o;1550:173::-;1618:20;;-1:-1:-1;;;;;1667:31:1;;1657:42;;1647:70;;1713:1;1710;1703:12;1647:70;1550:173;;;:::o;1728:300::-;1796:6;1804;1857:2;1845:9;1836:7;1832:23;1828:32;1825:52;;;1873:1;1870;1863:12;1825:52;1896:29;1915:9;1896:29;:::i;:::-;1886:39;1994:2;1979:18;;;;1966:32;;-1:-1:-1;;;1728:300:1:o;2267:186::-;2326:6;2379:2;2367:9;2358:7;2354:23;2350:32;2347:52;;;2395:1;2392;2385:12;2347:52;2418:29;2437:9;2418:29;:::i;2458:611::-;2648:2;2660:21;;;2730:13;;2633:18;;;2752:22;;;2600:4;;2831:15;;;2805:2;2790:18;;;2600:4;2874:169;2888:6;2885:1;2882:13;2874:169;;;2949:13;;2937:26;;2992:2;3018:15;;;;2983:12;;;;2910:1;2903:9;2874:169;;;-1:-1:-1;3060:3:1;;2458:611;-1:-1:-1;;;;;2458:611:1:o;3074:163::-;3141:20;;3201:10;3190:22;;3180:33;;3170:61;;3227:1;3224;3217:12;3242:298;3309:6;3317;3370:2;3358:9;3349:7;3345:23;3341:32;3338:52;;;3386:1;3383;3376:12;3338:52;3431:23;;;-1:-1:-1;3497:37:1;3530:2;3515:18;;3497:37;:::i;:::-;3487:47;;3242:298;;;;;:::o;3999:173::-;4067:20;;-1:-1:-1;;;;;4116:31:1;;4106:42;;4096:70;;4162:1;4159;4152:12;4177:493;4262:6;4270;4278;4286;4339:3;4327:9;4318:7;4314:23;4310:33;4307:53;;;4356:1;4353;4346:12;4307:53;4401:23;;;-1:-1:-1;4467:37:1;4500:2;4485:18;;4467:37;:::i;:::-;4457:47;-1:-1:-1;4577:2:1;4562:18;;4549:32;;-1:-1:-1;4626:38:1;4660:2;4645:18;;4626:38;:::i;:::-;4616:48;;4177:493;;;;;;;:::o;4675:127::-;4736:10;4731:3;4727:20;4724:1;4717:31;4767:4;4764:1;4757:15;4791:4;4788:1;4781:15;4807:275;4878:2;4872:9;4943:2;4924:13;;-1:-1:-1;;4920:27:1;4908:40;;-1:-1:-1;;;;;4963:34:1;;4999:22;;;4960:62;4957:88;;;5025:18;;:::i;:::-;5061:2;5054:22;4807:275;;-1:-1:-1;4807:275:1:o;5087:187::-;5136:4;-1:-1:-1;;;;;5161:6:1;5158:30;5155:56;;;5191:18;;:::i;:::-;-1:-1:-1;5257:2:1;5236:15;-1:-1:-1;;5232:29:1;5263:4;5228:40;;5087:187::o;5279:338::-;5344:5;5373:53;5389:36;5418:6;5389:36;:::i;:::-;5373:53;:::i;:::-;5364:62;;5449:6;5442:5;5435:21;5489:3;5480:6;5475:3;5471:16;5468:25;5465:45;;;5506:1;5503;5496:12;5465:45;5555:6;5550:3;5543:4;5536:5;5532:16;5519:43;5609:1;5602:4;5593:6;5586:5;5582:18;5578:29;5571:40;5279:338;;;;;:::o;5622:222::-;5665:5;5718:3;5711:4;5703:6;5699:17;5695:27;5685:55;;5736:1;5733;5726:12;5685:55;5758:80;5834:3;5825:6;5812:20;5805:4;5797:6;5793:17;5758:80;:::i;5849:687::-;5955:6;5963;5971;5979;6032:3;6020:9;6011:7;6007:23;6003:33;6000:53;;;6049:1;6046;6039:12;6000:53;6072:29;6091:9;6072:29;:::i;:::-;6062:39;;6120:38;6154:2;6143:9;6139:18;6120:38;:::i;:::-;6110:48;;6209:2;6198:9;6194:18;6181:32;-1:-1:-1;;;;;6228:6:1;6225:30;6222:50;;;6268:1;6265;6258:12;6222:50;6291;6333:7;6324:6;6313:9;6309:22;6291:50;:::i;:::-;6281:60;;;6394:2;6383:9;6379:18;6366:32;-1:-1:-1;;;;;6413:8:1;6410:32;6407:52;;;6455:1;6452;6445:12;6407:52;6478;6522:7;6511:8;6500:9;6496:24;6478:52;:::i;:::-;6468:62;;;5849:687;;;;;;;:::o;6541:374::-;6618:6;6626;6634;6687:2;6675:9;6666:7;6662:23;6658:32;6655:52;;;6703:1;6700;6693:12;6655:52;6726:29;6745:9;6726:29;:::i;:::-;6716:39;;6774:38;6808:2;6797:9;6793:18;6774:38;:::i;:::-;6541:374;;6764:48;;-1:-1:-1;;;6881:2:1;6866:18;;;;6853:32;;6541:374::o;7128:522::-;7222:6;7230;7238;7246;7254;7307:3;7295:9;7286:7;7282:23;7278:33;7275:53;;;7324:1;7321;7314:12;7275:53;7347:29;7366:9;7347:29;:::i;:::-;7337:39;;7395:38;7429:2;7418:9;7414:18;7395:38;:::i;:::-;7385:48;;7452:37;7485:2;7474:9;7470:18;7452:37;:::i;:::-;7442:47;-1:-1:-1;7558:2:1;7543:18;;7530:32;;-1:-1:-1;7605:39:1;7639:3;7624:19;;7605:39;:::i;:::-;7595:49;;7128:522;;;;;;;;:::o;7837:184::-;7895:6;7948:2;7936:9;7927:7;7923:23;7919:32;7916:52;;;7964:1;7961;7954:12;7916:52;7987:28;8005:9;7987:28;:::i;9086:118::-;9172:5;9165:13;9158:21;9151:5;9148:32;9138:60;;9194:1;9191;9184:12;9209:315;9274:6;9282;9335:2;9323:9;9314:7;9310:23;9306:32;9303:52;;;9351:1;9348;9341:12;9303:52;9374:29;9393:9;9374:29;:::i;:::-;9364:39;;9453:2;9442:9;9438:18;9425:32;9466:28;9488:5;9466:28;:::i;:::-;9513:5;9503:15;;;9209:315;;;;;:::o;9529:713::-;9624:6;9632;9640;9648;9701:3;9689:9;9680:7;9676:23;9672:33;9669:53;;;9718:1;9715;9708:12;9669:53;9741:29;9760:9;9741:29;:::i;:::-;9731:39;;9789:38;9823:2;9812:9;9808:18;9789:38;:::i;:::-;9779:48;-1:-1:-1;9896:2:1;9881:18;;9868:32;;-1:-1:-1;9975:2:1;9960:18;;9947:32;-1:-1:-1;;;;;9991:30:1;;9988:50;;;10034:1;10031;10024:12;9988:50;10057:22;;10110:4;10102:13;;10098:27;-1:-1:-1;10088:55:1;;10139:1;10136;10129:12;10088:55;10162:74;10228:7;10223:2;10210:16;10205:2;10201;10197:11;10162:74;:::i;10247:367::-;10310:8;10320:6;10374:3;10367:4;10359:6;10355:17;10351:27;10341:55;;10392:1;10389;10382:12;10341:55;-1:-1:-1;10415:20:1;;-1:-1:-1;;;;;10447:30:1;;10444:50;;;10490:1;10487;10480:12;10444:50;10527:4;10519:6;10515:17;10503:29;;10587:3;10580:4;10570:6;10567:1;10563:14;10555:6;10551:27;10547:38;10544:47;10541:67;;;10604:1;10601;10594:12;10541:67;10247:367;;;;;:::o;10619:551::-;10714:6;10722;10730;10783:2;10771:9;10762:7;10758:23;10754:32;10751:52;;;10799:1;10796;10789:12;10751:52;10839:9;10826:23;-1:-1:-1;;;;;10864:6:1;10861:30;10858:50;;;10904:1;10901;10894:12;10858:50;10943:70;11005:7;10996:6;10985:9;10981:22;10943:70;:::i;:::-;11032:8;;10917:96;;-1:-1:-1;11136:2:1;11121:18;;;;11108:32;;10619:551;-1:-1:-1;;;;10619:551:1:o;11175:495::-;11261:6;11269;11277;11285;11338:3;11326:9;11317:7;11313:23;11309:33;11306:53;;;11355:1;11352;11345:12;11306:53;11400:23;;;-1:-1:-1;11466:38:1;11500:2;11485:18;;11466:38;:::i;11675:768::-;11797:6;11805;11813;11821;11874:2;11862:9;11853:7;11849:23;11845:32;11842:52;;;11890:1;11887;11880:12;11842:52;11930:9;11917:23;-1:-1:-1;;;;;11955:6:1;11952:30;11949:50;;;11995:1;11992;11985:12;11949:50;12034:70;12096:7;12087:6;12076:9;12072:22;12034:70;:::i;:::-;12123:8;;-1:-1:-1;12008:96:1;-1:-1:-1;;12211:2:1;12196:18;;12183:32;-1:-1:-1;;;;;12227:32:1;;12224:52;;;12272:1;12269;12262:12;12224:52;12311:72;12375:7;12364:8;12353:9;12349:24;12311:72;:::i;:::-;11675:768;;;;-1:-1:-1;12402:8:1;-1:-1:-1;;;;11675:768:1:o;12448:258::-;12515:6;12523;12576:2;12564:9;12555:7;12551:23;12547:32;12544:52;;;12592:1;12589;12582:12;12544:52;12615:29;12634:9;12615:29;:::i;:::-;12605:39;;12663:37;12696:2;12685:9;12681:18;12663:37;:::i;12711:447::-;12796:6;12804;12812;12820;12873:3;12861:9;12852:7;12848:23;12844:33;12841:53;;;12890:1;12887;12880:12;12841:53;12913:29;12932:9;12913:29;:::i;:::-;12903:39;;12961:37;12994:2;12983:9;12979:18;12961:37;:::i;13163:260::-;13231:6;13239;13292:2;13280:9;13271:7;13267:23;13263:32;13260:52;;;13308:1;13305;13298:12;13260:52;13331:29;13350:9;13331:29;:::i;:::-;13321:39;;13379:38;13413:2;13402:9;13398:18;13379:38;:::i;13428:380::-;13507:1;13503:12;;;;13550;;;13571:61;;13625:4;13617:6;13613:17;13603:27;;13571:61;13678:2;13670:6;13667:14;13647:18;13644:38;13641:161;;13724:10;13719:3;13715:20;13712:1;13705:31;13759:4;13756:1;13749:15;13787:4;13784:1;13777:15;13813:127;13874:10;13869:3;13865:20;13862:1;13855:31;13905:4;13902:1;13895:15;13929:4;13926:1;13919:15;13945:127;14006:10;14001:3;13997:20;13994:1;13987:31;14037:4;14034:1;14027:15;14061:4;14058:1;14051:15;14077:135;14116:3;14137:17;;;14134:43;;14157:18;;:::i;:::-;-1:-1:-1;14204:1:1;14193:13;;14077:135::o;14217:170::-;14314:10;14307:18;;;14287;;;14283:43;;14338:20;;14335:46;;;14361:18;;:::i;14392:168::-;14465:9;;;14496;;14513:15;;;14507:22;;14493:37;14483:71;;14534:18;;:::i;14565:127::-;14626:10;14621:3;14617:20;14614:1;14607:31;14657:4;14654:1;14647:15;14681:4;14678:1;14671:15;14697:120;14737:1;14763;14753:35;;14768:18;;:::i;:::-;-1:-1:-1;14802:9:1;;14697:120::o;14822:198::-;-1:-1:-1;;;;;14922:27:1;;;14893;;;14889:61;;14962:29;;14959:55;;;14994:18;;:::i;15025:125::-;15090:9;;;15111:10;;;15108:36;;;15124:18;;:::i;15155:128::-;15222:9;;;15243:11;;;15240:37;;;15257:18;;:::i;15288:195::-;-1:-1:-1;;;;;15357:27:1;;;15386;;;15353:61;;15426:28;;15423:54;;;15457:18;;:::i;15488:167::-;15583:10;15556:18;;;15576;;;15552:43;;15607:19;;15604:45;;;15629:18;;:::i;16168:184::-;16238:6;16291:2;16279:9;16270:7;16266:23;16262:32;16259:52;;;16307:1;16304;16297:12;16259:52;-1:-1:-1;16330:16:1;;16168:184;-1:-1:-1;16168:184:1:o;17706:186::-;17765:6;17818:2;17806:9;17797:7;17793:23;17789:32;17786:52;;;17834:1;17831;17824:12;17786:52;17857:29;17876:9;17857:29;:::i;17897:301::-;18026:3;18064:6;18058:13;18110:6;18103:4;18095:6;18091:17;18086:3;18080:37;18172:1;18136:16;;18161:13;;;-1:-1:-1;18136:16:1;17897:301;-1:-1:-1;17897:301:1:o;18553:687::-;18633:6;18686:2;18674:9;18665:7;18661:23;18657:32;18654:52;;;18702:1;18699;18692:12;18654:52;18735:9;18729:16;-1:-1:-1;;;;;18760:6:1;18757:30;18754:50;;;18800:1;18797;18790:12;18754:50;18823:22;;18876:4;18868:13;;18864:27;-1:-1:-1;18854:55:1;;18905:1;18902;18895:12;18854:55;18938:2;18932:9;18963:53;18979:36;19008:6;18979:36;:::i;18963:53::-;19039:6;19032:5;19025:21;19087:7;19082:2;19073:6;19069:2;19065:15;19061:24;19058:37;19055:57;;;19108:1;19105;19098:12;19055:57;19156:6;19151:2;19147;19143:11;19138:2;19131:5;19127:14;19121:42;19208:1;19183:18;;;19203:2;19179:27;19172:38;;;;19187:5;18553:687;-1:-1:-1;;;;18553:687:1:o;19245:185::-;19283:3;19327:10;19320:5;19316:22;19357:7;19347:41;;19368:18;;:::i;:::-;-1:-1:-1;;19404:20:1;;19245:185;-1:-1:-1;;19245:185:1:o;21857:178::-;21896:1;21930:10;21927:1;21923:18;21960:3;21950:37;;21967:18;;:::i;:::-;22025:3;22012:10;22009:1;22005:18;22001:28;21996:33;;;21857:178;;;;:::o;22040:244::-;22151:10;22124:18;;;22144;;;22120:43;22183:28;;;;22230:24;;;22220:58;;22258:18;;:::i;:::-;22220:58;22040:244;;;;:::o;22289:241::-;22328:7;22407:1;22403:2;22392:17;22388:1;22384:2;22373:17;22369:41;22445:11;22441:2;22430:27;22419:38;;22488:11;22479:7;22476:24;22466:58;;22504:18;;:::i;22535:219::-;22635:2;22624:17;;;22605;;;;22601:41;-1:-1:-1;;;;;;22657:35:1;;-1:-1:-1;;;;;22694:30:1;;22654:71;22651:97;;;22728:18;;:::i;22759:215::-;22857:2;22827:17;;;22846;;;;22823:41;-1:-1:-1;;;;;22879:29:1;;-1:-1:-1;;;;;;22910:34:1;;22876:69;22873:95;;;22948:18;;:::i;22979:197::-;23019:1;-1:-1:-1;;;;;23046:27:1;;;23082:37;;23099:18;;:::i;:::-;-1:-1:-1;;;;;23137:27:1;;;;23133:37;;;;;22979:197;-1:-1:-1;;22979:197:1:o;23709:518::-;23811:2;23806:3;23803:11;23800:421;;;23847:5;23844:1;23837:16;23891:4;23888:1;23878:18;23961:2;23949:10;23945:19;23942:1;23938:27;23932:4;23928:38;23997:4;23985:10;23982:20;23979:47;;;-1:-1:-1;24020:4:1;23979:47;24075:2;24070:3;24066:12;24063:1;24059:20;24053:4;24049:31;24039:41;;24130:81;24148:2;24141:5;24138:13;24130:81;;;24207:1;24193:16;;24174:1;24163:13;24130:81;;24403:1299;24529:3;24523:10;-1:-1:-1;;;;;24548:6:1;24545:30;24542:56;;;24578:18;;:::i;:::-;24607:97;24697:6;24657:38;24689:4;24683:11;24657:38;:::i;:::-;24651:4;24607:97;:::i;:::-;24753:4;24784:2;24773:14;;24801:1;24796:649;;;;25489:1;25506:6;25503:89;;;-1:-1:-1;25558:19:1;;;25552:26;25503:89;-1:-1:-1;;24360:1:1;24356:11;;;24352:24;24348:29;24338:40;24384:1;24380:11;;;24335:57;25605:81;;24766:930;;24796:649;23656:1;23649:14;;;23693:4;23680:18;;-1:-1:-1;;24832:20:1;;;24950:222;24964:7;24961:1;24958:14;24950:222;;;25046:19;;;25040:26;25025:42;;25153:4;25138:20;;;;25106:1;25094:14;;;;24980:12;24950:222;;;24954:3;25200:6;25191:7;25188:19;25185:201;;;25261:19;;;25255:26;-1:-1:-1;;25344:1:1;25340:14;;;25356:3;25336:24;25332:37;25328:42;25313:58;25298:74;;25185:201;-1:-1:-1;;;;25432:1:1;25416:14;;;25412:22;25399:36;;-1:-1:-1;24403:1299:1:o;25707:245::-;25774:6;25827:2;25815:9;25806:7;25802:23;25798:32;25795:52;;;25843:1;25840;25833:12;25795:52;25875:9;25869:16;25894:28;25916:5;25894:28;:::i;26368:485::-;-1:-1:-1;;;;;26599:32:1;;;26581:51;;26668:32;;26663:2;26648:18;;26641:60;26732:2;26717:18;;26710:34;;;26780:3;26775:2;26760:18;;26753:31;;;-1:-1:-1;;26801:46:1;;26827:19;;26819:6;26801:46;:::i;26858:249::-;26927:6;26980:2;26968:9;26959:7;26955:23;26951:32;26948:52;;;26996:1;26993;26986:12;26948:52;27028:9;27022:16;27047:30;27071:5;27047:30;:::i
Swarm Source
ipfs://67e3af8533ff98de13a52b43c98b05d159ba2d938981171b49d2e31bbb9f5c14
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.