Source Code
Overview
S Balance
Token Holdings
More Info
ContractCreator
TokenTracker
Latest 11 from a total of 11 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Extend Lock | 21662265 | 33 days ago | IN | 0 S | 0.00030766 | ||||
Extend Lock | 21661593 | 33 days ago | IN | 0 S | 0.00030766 | ||||
Extend Lock | 21659454 | 33 days ago | IN | 0 S | 0.00030754 | ||||
Extend Lock | 21654581 | 33 days ago | IN | 0 S | 0.00030754 | ||||
Extend Lock | 21654288 | 33 days ago | IN | 0 S | 0.00030829 | ||||
Extend Lock | 21654275 | 33 days ago | IN | 0 S | 0.00030829 | ||||
Set Art Proxy | 21650544 | 33 days ago | IN | 0 S | 0.0000403 | ||||
Create Lock | 21647142 | 33 days ago | IN | 0 S | 0.00030154 | ||||
Create Lock | 21624041 | 33 days ago | IN | 0 S | 0.00032682 | ||||
Create Lock | 21623635 | 33 days ago | IN | 0 S | 0.00029929 | ||||
Un Pause | 21616607 | 33 days ago | IN | 0 S | 0.00003857 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
VeSix
Compiler Version
v0.8.27+commit.40a35a09
Contract Source Code (Solidity)
/** *Submitted for verification at testnet.sonicscan.org on 2025-02-19 */ // 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 Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } 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 ERC165 is IERC165 { /** * @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 ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors { using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; mapping(uint256 tokenId => address) private _owners; mapping(address owner => uint256) private _balances; mapping(uint256 tokenId => address) private _tokenApprovals; mapping(address owner => mapping(address operator => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual returns (uint256) { 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) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual returns (string memory) { 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) { 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) { 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) { 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 { 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) { 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 { // 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 { 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.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); } pragma solidity ^0.8.20; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); } pragma solidity ^0.8.20; /** * @title SafeERC20 * @dev Wrappers around ERC-20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @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(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (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(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, 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. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @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. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @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 {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @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 silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } } pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @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; } } 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 Pausable is Context { /** * @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. */ constructor() { _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()); } } 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 Ownable is Context { address private _owner; /** * @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. */ constructor(address initialOwner) { 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) { 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 { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } pragma solidity 0.8.27; interface IRewardsDistributor { function claim(uint256 tokenId) external returns (uint256); function claimable(uint256 tokenId) external view returns (uint256); function checkpoint_token() external; function checkpoint_total_supply() external; function getRewardForDuration() external view returns (uint256); } //@author 0xPhant0m based on Andre Cronje's voteEscrow contract for Solidly pragma solidity 0.8.27; contract VeSix is ERC721, ReentrancyGuard, Pausable, Ownable { using SafeERC20 for IERC20; // Custom errors error InvalidAmount(); error InvalidDuration(); error TransferFailed(); error NotTokenOwner(); error LockNotExpired(); error ZeroReward(); error InvalidToken(); error InvalidArtProxy(); error ZeroAddress(); error DeadlineExpired(); 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 IERC20 private immutable i_lockedToken; IRewardsDistributor private immutable i_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 ); constructor( address lockedToken, address distributor, address emergencyRecovery, string memory name, string memory symbol ) ERC721(name, symbol) Ownable(msg.sender) { if (lockedToken == address(0) || distributor == address(0) || emergencyRecovery == address(0)) revert ZeroAddress(); _pause(); i_lockedToken = IERC20(lockedToken); i_distributor = IRewardsDistributor(distributor); _emergencyRecoveryAddress = emergencyRecovery; // Initialize point history pointHistory[0].blk = uint32(block.number); pointHistory[0].ts = uint32(block.timestamp); } // Modifiers modifier validDeadline(uint256 deadline) { if (block.timestamp > deadline) revert DeadlineExpired(); _; } modifier checkRewardRate() { if (i_distributor.getRewardForDuration() > MAX_REWARD_RATE) revert MaxRewardRateExceeded(); _; } function getCurrentMultiplier(uint256 tokenId) public view returns (uint128) { LockPosition memory lock = _locks[tokenId]; if (uint32(block.timestamp) >= lock.endTime) return BASE_MULTIPLIER; uint32 timeLeft; unchecked { timeLeft = lock.endTime - uint32(block.timestamp); } return uint128(BASE_MULTIPLIER + (uint256(lock.slope) * timeLeft)); } 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; 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; 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; } function _processWeeklyCheckpoints( Point memory lastPoint, uint32 lastCheckpoint, uint128 blockSlope, uint32 _epoch ) internal returns (Point memory) { Point memory initialLastPoint = lastPoint; uint32 ti = (lastCheckpoint / WEEK) * WEEK; for (uint256 i = 0; i < 255; ++i) { ti += WEEK; int128 dslope = 0; if (ti > uint32(block.timestamp)) { ti = uint32(block.timestamp); } else { dslope = slopeChanges[ti]; } lastPoint.bias -= lastPoint.slope * int128(uint128(ti - lastCheckpoint)); lastPoint.slope += dslope; lastPoint.ts = ti; lastPoint.blk = uint32(initialLastPoint.blk + (uint256(blockSlope) * (ti - initialLastPoint.ts)) / PRECISION); if (ti == uint32(block.timestamp)) { lastPoint.blk = uint32(block.number); break; } else { pointHistory[_epoch + 1 + uint32(i)] = lastPoint; } lastCheckpoint = ti; } return lastPoint; } function _checkpointToken( uint256 tokenId, LockedBalance memory oldLocked, LockedBalance memory newLocked ) internal { Point memory uOld; Point memory uNew; if (oldLocked.end > uint32(block.timestamp) && oldLocked.amount > 0) { uOld.slope = oldLocked.amount / iMAXTIME; uOld.bias = uOld.slope * int128(uint128(oldLocked.end - uint32(block.timestamp))); } if (newLocked.end > uint32(block.timestamp) && newLocked.amount > 0) { uNew.slope = newLocked.amount / iMAXTIME; uNew.bias = uNew.slope * int128(uint128(newLocked.end - uint32(block.timestamp))); } _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 _processTokenSlopeChanges( LockedBalance memory oldLocked, LockedBalance memory newLocked, int128 oldSlope, int128 newSlope ) internal { if (oldLocked.end > uint32(block.timestamp)) { int128 oldDslope = slopeChanges[oldLocked.end]; oldDslope += oldSlope; if (newLocked.end == oldLocked.end) { oldDslope -= newSlope; } slopeChanges[oldLocked.end] = oldDslope; } if (newLocked.end > uint32(block.timestamp)) { if (newLocked.end > oldLocked.end) { int128 newDslope = slopeChanges[newLocked.end]; newDslope -= newSlope; slopeChanges[newLocked.end] = newDslope; } } } function _beforeTokenTransfer( address from, uint256 tokenId ) internal { if (from != address(0) && address(i_distributor) != address(0)) { // Skip if minting i_distributor.claim(tokenId); } } function transferFrom(address from, address to, uint256 tokenId) public virtual override { _beforeTokenTransfer(from, tokenId); super.transferFrom(from,to, tokenId); } function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override { _beforeTokenTransfer(from, tokenId); super.safeTransferFrom(from, to, tokenId, data); } function withdraw(uint256 tokenId) external nonReentrant { 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; LockedBalance memory oldLock = LockedBalance({ amount: int128(uint128(amount)), end: lock.endTime }); delete _locks[tokenId]; uint128 multiplier = getCurrentMultiplier(tokenId); uint256 weightedAmount = (uint256(amount) * uint256(multiplier)) / PRECISION; if (weightedAmount / uint256(amount) != uint256(multiplier)) revert ArithmeticError(); uint256 weightedSupplyIncrease = weightedAmount / PRECISION; if (weightedSupplyIncrease > type(uint128).max) revert InvalidAmount(); _totalWeightedSupply -= uint128(weightedSupplyIncrease); _checkpoint(tokenId, oldLock, LockedBalance(0, 0)); delete userPointEpoch[tokenId]; _burn(tokenId); unchecked { _userLockCount[msg.sender]--; } i_lockedToken.safeTransfer(msg.sender, amount); emit Withdraw(msg.sender, tokenId, amount); } function _calculateLockParameters( uint128 amount, uint32 lockDuration, uint128 minMultiplier ) internal pure returns (uint128 slope, uint128 multiplier) { // Calculate slope with safe math uint256 slopeCalc = (uint256(amount) * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / MAXTIME; if (slopeCalc > type(uint128).max) revert InvalidAmount(); slope = uint128(slopeCalc); // Verify minimum multiplier multiplier = uint128(BASE_MULTIPLIER + (uint256(slope) * lockDuration)); if (multiplier < minMultiplier) revert SlippageExceeded(); } function _updateWeightedSupply(uint128 amount, uint128 multiplier) internal { uint256 weightedAmount = uint256(amount) * uint256(multiplier); if (weightedAmount / uint256(amount) != uint256(multiplier)) revert ArithmeticError(); uint256 weightedSupplyIncrease = weightedAmount / PRECISION; if (weightedSupplyIncrease > type(uint128).max) revert InvalidAmount(); _totalWeightedSupply += uint128(weightedSupplyIncrease); } function createLock( uint128 amount, uint32 lockDuration, uint256 deadline, uint128 minMultiplier ) external nonReentrant whenNotPaused validDeadline(deadline) returns (uint256 tokenId) { if (amount == 0) revert InvalidAmount(); if (lockDuration == 0 || lockDuration > MAXTIME) revert InvalidDuration(); if (_userLockCount[msg.sender] >= 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 = i_lockedToken.balanceOf(address(this)); i_lockedToken.safeTransferFrom(msg.sender, address(this), amount); if (i_lockedToken.balanceOf(address(this)) != balanceBefore + amount) revert TransferFailed(); unchecked { tokenId = _nextTokenId++; _userLockCount[msg.sender]++; } _safeMint(msg.sender, tokenId); _locks[tokenId] = LockPosition({ amount: amount, endTime: unlockTime, lastUpdate: uint32(block.timestamp), slope: slope }); _updateWeightedSupply(amount, multiplier); emit Deposit(msg.sender, tokenId, amount, unlockTime); } function extendLock( uint256 tokenId, uint32 newDuration, uint256 deadline, uint128 minMultiplier ) external nonReentrant whenNotPaused validDeadline(deadline) { // Check ownership if (ownerOf(tokenId) != msg.sender) revert NotTokenOwner(); // Get current lock LockPosition memory lock = _locks[tokenId]; if (lock.amount == 0) revert LockNotExists(); // Check if lock is expired if (uint32(block.timestamp) >= lock.endTime) revert LockNotExpired(); // Calculate new end time uint32 newEndTime = uint32(block.timestamp) + newDuration; if (newDuration == 0 || newEndTime > uint32(block.timestamp) + MAXTIME) revert InvalidDuration(); // Calculate new slope uint256 slopeCalc = (uint256(lock.amount) * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / MAXTIME; if (slopeCalc > type(uint128).max) revert InvalidAmount(); uint128 newSlope = uint128(slopeCalc); // Calculate new multiplier and verify against minimum uint128 multiplier = uint128(BASE_MULTIPLIER + (uint256(newSlope) * newDuration)); if (multiplier < minMultiplier) revert SlippageExceeded(); if (multiplier > MAX_MULTIPLIER) revert MultiplierTooHigh(); // Create old and new lock balances for checkpoint LockedBalance memory oldLocked = LockedBalance({ amount: int128(uint128(lock.amount)), end: lock.endTime }); LockedBalance memory newLocked = LockedBalance({ amount: int128(uint128(lock.amount)), end: newEndTime }); // Update state _locks[tokenId] = LockPosition({ amount: lock.amount, endTime: newEndTime, lastUpdate: uint32(block.timestamp), slope: newSlope }); // Update weighted supply uint256 oldWeightedAmount = (uint256(lock.amount) * getCurrentMultiplier(tokenId)) / PRECISION; uint256 newWeightedAmount = (uint256(lock.amount) * multiplier) / PRECISION; _totalWeightedSupply = _totalWeightedSupply - uint128(oldWeightedAmount) + uint128(newWeightedAmount); // Checkpoint _checkpoint(tokenId, oldLocked, newLocked); emit LockExtended(msg.sender, tokenId, newEndTime, multiplier); } function increaseLockAmount( uint256 tokenId, uint128 additionalAmount, uint256 deadline, uint128 minMultiplier ) external nonReentrant whenNotPaused validDeadline(deadline) { if (ownerOf(tokenId) != msg.sender) revert NotTokenOwner(); if (additionalAmount == 0) revert InvalidAmount(); LockPosition memory lock = _locks[tokenId]; if (lock.amount == 0) revert LockNotExists(); if (uint32(block.timestamp) >= lock.endTime) revert LockNotExpired(); uint32 remainingDuration = lock.endTime - uint32(block.timestamp); uint128 newAmount = lock.amount + additionalAmount; // Calculate new multiplier using existing function uint128 multiplier = getExpectedMultiplier(newAmount, remainingDuration); if (multiplier < minMultiplier) revert SlippageExceeded(); // Transfer tokens first uint256 balanceBefore = i_lockedToken.balanceOf(address(this)); i_lockedToken.safeTransferFrom(msg.sender, address(this), additionalAmount); if (i_lockedToken.balanceOf(address(this)) != balanceBefore + additionalAmount) revert TransferFailed(); // Create checkpoint structs LockedBalance memory oldLocked = LockedBalance({ amount: int128(uint128(lock.amount)), end: lock.endTime }); LockedBalance memory newLocked = LockedBalance({ amount: int128(uint128(newAmount)), end: lock.endTime }); // Update state _locks[tokenId].amount = newAmount; _locks[tokenId].slope = uint128((uint256(newAmount) * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / MAXTIME); _locks[tokenId].lastUpdate = uint32(block.timestamp); // Checkpoint and update weighted supply _checkpoint(tokenId, oldLocked, newLocked); emit AmountIncreased(msg.sender, tokenId, additionalAmount, newAmount, multiplier); } 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) { Point memory lastPoint = point; uint32 ti = (lastPoint.ts / WEEK) * WEEK; for (uint256 i = 0; i < 255; ++i) { ti += WEEK; int128 dslope = 0; if (ti > t) { ti = t; } else { dslope = slopeChanges[ti]; } lastPoint.bias -= lastPoint.slope * int128(uint128(ti - lastPoint.ts)); if (ti == t) { break; } lastPoint.slope += dslope; lastPoint.ts = ti; } if (lastPoint.bias < 0) { lastPoint.bias = 0; } return uint128(uint256(uint128(lastPoint.bias))); } function _calculateMultiplier(uint128 slope, uint32 duration) internal pure returns (uint128) { uint256 multiplierIncrease = uint256(slope) * duration; uint256 totalMultiplier = BASE_MULTIPLIER + multiplierIncrease; if (totalMultiplier > MAX_MULTIPLIER) revert MultiplierTooHigh(); if (totalMultiplier < BASE_MULTIPLIER) revert InvalidMultiplier(); return uint128(totalMultiplier); } function merge( uint256[] calldata tokenIds, uint256 deadline ) external nonReentrant whenNotPaused validDeadline(deadline) { if (tokenIds.length < 2) revert InvalidAmount(); uint128 totalAmount; uint32 latestEndTime; // First pass: validate ownership and calculate totals for (uint256 i = 0; i < tokenIds.length; i++) { if (ownerOf(tokenIds[i]) != msg.sender) revert NotTokenOwner(); LockPosition memory lock = _locks[tokenIds[i]]; totalAmount += lock.amount; if (lock.endTime > latestEndTime) { latestEndTime = lock.endTime; } } // Create new merged position uint32 remainingDuration = latestEndTime - uint32(block.timestamp); if (remainingDuration > MAXTIME) revert InvalidDuration(); uint256 slopeCalc = (uint256(totalAmount) * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / MAXTIME; if (slopeCalc > type(uint128).max) revert InvalidAmount(); uint128 newSlope = uint128(slopeCalc); uint256 newTokenId = ++_nextTokenId; _safeMint(msg.sender, newTokenId); // Checkpoint and cleanup old positions for (uint256 i = 0; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; LockPosition memory oldLock = _locks[tokenId]; LockedBalance memory oldLockedBalance = LockedBalance({ amount: int128(uint128(oldLock.amount)), end: oldLock.endTime }); _checkpoint(tokenId, oldLockedBalance, LockedBalance(0, 0)); delete _locks[tokenId]; _burn(tokenId); } // Create new lock LockedBalance memory newLock = LockedBalance({ amount: int128(uint128(totalAmount)), end: latestEndTime }); _checkpoint(newTokenId, LockedBalance(0, 0), newLock); _locks[newTokenId] = LockPosition({ amount: totalAmount, endTime: latestEndTime, lastUpdate: uint32(block.timestamp), slope: newSlope }); 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) { uint32 userEpoch = userPointEpoch[tokenId]; if (userEpoch == 0) return 0; Point memory lastPoint = userPointHistory[tokenId][userEpoch]; lastPoint.bias -= lastPoint.slope * int128(uint128(timestamp - lastPoint.ts)); if (lastPoint.bias < 0) { lastPoint.bias = 0; } return uint128(uint256(uint128(lastPoint.bias))); } function getMinMultiplier(uint128 amount, uint32 lockDuration) public view returns (uint128) { // Reduce duration by max block drift uint32 minDuration = lockDuration > MAX_BLOCK_DRIFT ? lockDuration - MAX_BLOCK_DRIFT : lockDuration; // Calculate multiplier with reduced duration uint256 slopeCalc = (uint256(amount) * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / MAXTIME; uint128 slope = uint128(slopeCalc); return uint128(BASE_MULTIPLIER + (uint256(slope) * 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]--; } i_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 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 getExpectedMultiplier(uint128 amount, uint32 duration) public pure returns (uint128) { if (duration == 0 || duration > MAXTIME) revert InvalidDuration(); if (amount == 0) revert InvalidAmount(); // Calculate slope uint256 slopeCalc = (uint256(amount) * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / MAXTIME; if (slopeCalc > type(uint128).max) revert InvalidAmount(); uint128 slope = uint128(slopeCalc); // Calculate multiplier uint256 multiplierIncrease = uint256(slope) * duration; uint256 totalMultiplier = BASE_MULTIPLIER + multiplierIncrease; if (totalMultiplier > MAX_MULTIPLIER) revert MultiplierTooHigh(); if (totalMultiplier < BASE_MULTIPLIER) revert InvalidMultiplier(); return uint128(totalMultiplier); } }
Contract ABI
API[{"inputs":[{"internalType":"address","name":"lockedToken","type":"address"},{"internalType":"address","name":"distributor","type":"address"},{"internalType":"address","name":"emergencyRecovery","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"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":"InvalidMultiplier","type":"error"},{"inputs":[],"name":"InvalidRewardRate","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"LockNotExists","type":"error"},{"inputs":[],"name":"LockNotExpired","type":"error"},{"inputs":[],"name":"MaxRewardRateExceeded","type":"error"},{"inputs":[],"name":"MultiplierTooHigh","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":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","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":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":"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":"newDuration","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":[{"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":"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":[{"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":"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":"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":"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
60c0604052600f805463ffffffff60a01b1916600f60a01b179055348015610025575f5ffd5b506040516149473803806149478339810160408190526100449161033c565b3382825f6100528382610456565b50600161005f8282610456565b50506001600655506007805460ff191690556001600160a01b03811661009f57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100a881610189565b506001600160a01b03851615806100c657506001600160a01b038416155b806100d857506001600160a01b038316155b156100f65760405163d92e233d60e01b815260040160405180910390fd5b6100fe6101e2565b50506001600160a01b0392831660805290821660a052601180546001600160a01b031916919092161790555f8052600a6020527f13da86008ba1c6922daee3e07db95305ef49ebced9f5467a0b8613fcc6b343e480546001600160401b0319166401000000004363ffffffff9081169190910263ffffffff1916919091174291909116179055610510565b600780546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6101ea61023c565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861021f3390565b6040516001600160a01b03909116815260200160405180910390a1565b60075460ff16156102825760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610096565b565b80516001600160a01b038116811461029a575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126102c2575f5ffd5b81516001600160401b038111156102db576102db61029f565b604051601f8201601f19908116603f011681016001600160401b03811182821017156103095761030961029f565b604052818152838201602001851015610320575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f5f5f5f60a08688031215610350575f5ffd5b61035986610284565b945061036760208701610284565b935061037560408701610284565b60608701519093506001600160401b03811115610390575f5ffd5b61039c888289016102b3565b608088015190935090506001600160401b038111156103b9575f5ffd5b6103c5888289016102b3565b9150509295509295909350565b600181811c908216806103e657607f821691505b60208210810361040457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561045157805f5260205f20601f840160051c8101602085101561042f5750805b601f840160051c820191505b8181101561044e575f815560010161043b565b50505b505050565b81516001600160401b0381111561046f5761046f61029f565b6104838161047d84546103d2565b8461040a565b6020601f8211600181146104b5575f831561049e5750848201515b5f19600385901b1c1916600184901b17845561044e565b5f84815260208120601f198516915b828110156104e457878501518255602094850194600190920191016104c4565b508482101561050157868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b60805160a0516143de6105695f395f818161295f01526129a501525f818161110a0152818161133301528181611c6801528181611ce801528181611d410152818161251c0152818161259c01526125f501526143de5ff3fe608060405234801561000f575f5ffd5b5060043610610260575f3560e01c80638b25e8c11161014b578063beb83109116100bf578063df0c78ef11610084578063df0c78ef146106dd578063df215157146106f0578063e58f594714610703578063e985e9c514610728578063f2fde38b1461073b578063f7b188a51461074e575f5ffd5b8063beb8310914610689578063c5b1c7d01461069c578063c87b56dd146106a4578063d89dd269146106b7578063ddacc94a146106ca575f5ffd5b806397612d4b1161011057806397612d4b146105de5780639b7d02ad146105f1578063a22cb4651461062e578063b88d4fde14610641578063bbe33ea514610654578063bcc0022514610667575f5ffd5b80638b25e8c1146105415780638da5cb5b146105545780638ff424901461056a578063900cf0cf146105b157806395d89b41146105d6575f5ffd5b80632e1a7d4d116101e2578063586c2600116101a7578063586c2600146104425780635c975abb146104775780636352211e1461048257806370a0823114610495578063715018a6146104b657806389f839c6146104be575f5ffd5b80632e1a7d4d146103e35780632e720f7d146103f657806342842e0e146104095780635312ea8e1461041c5780635594a0451461042f575f5ffd5b80631d237a49116102285780631d237a49146103015780631f5ab0221461038657806320a194b81461039957806323b872dd146103ab578063268dc199146103be575f5ffd5b806301ffc9a71461026457806306fdde031461028c578063081812fc146102a1578063095ea7b3146102cc57806313de148b146102e1575b5f5ffd5b610277610272366004613bed565b610756565b60405190151581526020015b60405180910390f35b6102946107a7565b6040516102839190613c36565b6102b46102af366004613c48565b610836565b6040516001600160a01b039091168152602001610283565b6102df6102da366004613c7a565b61085d565b005b6102f46102ef366004613ca2565b61086c565b6040516102839190613cbb565b61035361030f366004613d10565b600d60209081525f928352604080842090915290825290208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b60408051600f95860b81529390940b602084015263ffffffff918216938301939093529091166060820152608001610283565b6102df610394366004613d50565b610960565b601154600160a01b900460ff16610277565b6102df6103b9366004613d93565b610e2c565b6010546001600160801b03165b6040516001600160801b039091168152602001610283565b6102df6103f1366004613c48565b610e46565b6102df610404366004613ca2565b61118e565b6102df610417366004613d93565b6111df565b6102df61042a366004613c48565b6111f9565b600f546102b4906001600160a01b031681565b610464610450366004613dcd565b600e6020525f9081526040902054600f0b81565b604051600f9190910b8152602001610283565b60075460ff16610277565b6102b4610490366004613c48565b6113af565b6104a86104a3366004613ca2565b6113b9565b604051908152602001610283565b6102df6113fe565b61050a6104cc366004613c48565b60086020525f9081526040902080546001909101546001600160801b0380831692600160801b9004169063ffffffff80821691600160201b90041684565b604080516001600160801b03958616815294909316602085015263ffffffff91821692840192909252166060820152608001610283565b6103cb61054f366004613c48565b611411565b60075461010090046001600160a01b03166102b4565b610353610578366004613dcd565b600a6020525f908152604090208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b600b546105c19063ffffffff1681565b60405163ffffffff9091168152602001610283565b6102946114c3565b6103cb6105ec366004613dcd565b6114d2565b61061c6105ff366004613ca2565b6001600160a01b03165f9081526009602052604090205460ff1690565b60405160ff9091168152602001610283565b6102df61063c366004613de6565b61153e565b6102df61064f366004613e8b565b611549565b6102df610662366004613f2f565b61155f565b61061c610675366004613ca2565b60096020525f908152604090205460ff1681565b6102df610697366004613fa4565b611ab5565b6102df611f2e565b6102946106b2366004613c48565b611f94565b6103cb6106c5366004613fc7565b6120e3565b6103cb6106d8366004613d10565b612244565b6103cb6106eb366004613fc7565b612321565b6104a86106fe366004613fef565b6123d5565b6105c1610711366004613c48565b600c6020525f908152604090205463ffffffff1681565b610277610736366004614019565b6127d6565b6102df610749366004613ca2565b612803565b6102df61283d565b5f6001600160e01b031982166380ac58cd60e01b148061078657506001600160e01b03198216635b5e139f60e01b145b806107a157506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f80546107b590614041565b80601f01602080910402602001604051908101604052809291908181526020018280546107e190614041565b801561082c5780601f106108035761010080835404028352916020019161082c565b820191905f5260205f20905b81548152906001019060200180831161080f57829003601f168201915b5050505050905090565b5f6108408261284d565b505f828152600460205260409020546001600160a01b03166107a1565b610868828233612885565b5050565b6001600160a01b0381165f9081526009602052604090205460609060ff168067ffffffffffffffff8111156108a3576108a3613e1f565b6040519080825280602002602001820160405280156108cc578160200160208202803683370190505b5091508060ff165f036108df5750919050565b5f805b600754600160a81b900463ffffffff16811015610958575f818152600260205260409020546001600160a01b03868116911603610950578084838151811061092c5761092c614079565b602090810291909101015281610941816140a1565b9250508260ff16821015610958575b6001016108e2565b505050919050565b610968612892565b6109706128eb565b818042111561099257604051631ab7da6b60e01b815260040160405180910390fd5b3361099c866113af565b6001600160a01b0316146109c3576040516359dc379f60e01b815260040160405180910390fd5b5f858152600860209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b900490911660608201529103610a3e57604051632254ea3d60e11b815260040160405180910390fd5b806040015163ffffffff164263ffffffff1610610a6e5760405163342ad40160e11b815260040160405180910390fd5b5f610a7986426140b9565b905063ffffffff86161580610aa55750610a9662ed4e00426140b9565b63ffffffff168163ffffffff16115b15610ac357604051637616640160e01b815260040160405180910390fd5b5f62ed4e00610ae2670de0b6b3a7640000673782dace9d9000006140d5565b8451610afa916001600160801b0390811691166140f4565b610b04919061411f565b90506001600160801b03811115610b2e5760405163162908e360e11b815260040160405180910390fd5b805f610b4963ffffffff8a166001600160801b0384166140f4565b610b5b90670de0b6b3a7640000614132565b9050866001600160801b0316816001600160801b03161015610b9057604051638199f5f360e01b815260040160405180910390fd5b673782dace9d9000006001600160801b0382161115610bc257604051638f651fb760e01b815260040160405180910390fd5b5f6040518060400160405280875f0151600f0b8152602001876040015163ffffffff1681525090505f6040518060400160405280885f0151600f0b81526020018763ffffffff1681525090506040518060800160405280885f01516001600160801b03168152602001856001600160801b031681526020018763ffffffff1681526020014263ffffffff1681525060085f8e81526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055509050505f670de0b6b3a76400006001600160801b0316610d238e611411565b8951610d3b916001600160801b0390811691166140f4565b610d45919061411f565b88519091505f90670de0b6b3a764000090610d6c906001600160801b0388811691166140f4565b610d76919061411f565b6010549091508190610d929084906001600160801b03166140d5565b610d9c9190614145565b601080546001600160801b0319166001600160801b0392909216919091179055610dc78e8585612931565b6040805163ffffffff8a1681526001600160801b03871660208201528f9133917f3032be442129e161b4ae1cdee94871a69de2c16ee2007f31fc209a715673455c910160405180910390a350505050505050505050610e266001600655565b50505050565b610e36838261294a565b610e41838383612a17565b505050565b610e4e612892565b5f818152600260205260409020546001600160a01b031680610e8257604051626f708760e21b815260040160405180910390fd5b6001600160a01b0381163314610eab576040516359dc379f60e01b815260040160405180910390fd5b5f828152600860209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b900490911660608201529103610f2657604051632254ea3d60e11b815260040160405180910390fd5b806040015163ffffffff164263ffffffff161015610f575760405163342ad40160e11b815260040160405180910390fd5b8051604080518082018252600f83900b81528184015163ffffffff166020808301919091525f8781526008909152918220828155600101805467ffffffffffffffff1916905590610fa786611411565b90505f670de0b6b3a7640000610fc96001600160801b038085169087166140f4565b610fd3919061411f565b9050816001600160801b0316846001600160801b031682610ff4919061411f565b1461101257604051630fc12e3560e11b815260040160405180910390fd5b5f611025670de0b6b3a76400008361411f565b90506001600160801b0381111561104f5760405163162908e360e11b815260040160405180910390fd5b601080548291905f9061106c9084906001600160801b03166140d5565b92506101000a8154816001600160801b0302191690836001600160801b031602179055506110b8888560405180604001604052805f600f0b81526020015f63ffffffff16815250612931565b5f888152600c60205260409020805463ffffffff191690556110d988612a9a565b335f818152600960205260409020805460ff19811660ff9182165f190190911617905561113a906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906001600160801b038816612ad2565b6040516001600160801b0386168152889033907f8903a5b5d08a841e7f68438387f1da20c84dea756379ed37e633ff3854b99b849060200160405180910390a35050505050505061118b6001600655565b50565b611196612b31565b6001600160a01b0381166111bd5760405163d92e233d60e01b815260040160405180910390fd5b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b610e4183838360405180602001604052805f815250611549565b611201612892565b601154600160a01b900460ff166112575760405162461bcd60e51b81526020600482015260156024820152744e6f7420696e20656d657267656e6379206d6f646560581b60448201526064015b60405180910390fd5b33611261826113af565b6001600160a01b031614611288576040516359dc379f60e01b815260040160405180910390fd5b5f818152600860208181526040808420815160808101835281546001600160801b03808216808452600160801b909204168286015260018301805463ffffffff80821696850196909652600160201b810490951660608401528888529590945294905567ffffffffffffffff191690915561130283612a9a565b335f818152600960205260409020805460ff19811660ff9182165f1901909116179055611363906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906001600160801b038416612ad2565b6040516001600160801b0382168152839033907f4f27eb511b2a4633cfb633ac1c4a99b4c298ca6488b29ec26f3504a5927f67289060200160405180910390a3505061118b6001600655565b5f6107a18261284d565b5f6001600160a01b0382166113e3576040516322718ad960e21b81525f600482015260240161124e565b506001600160a01b03165f9081526003602052604090205490565b611406612b31565b61140f5f612b64565b565b5f818152600860209081526040808320815160808101835281546001600160801b038082168352600160801b90910416938101939093526001015463ffffffff808216928401839052600160201b909104811660608401524216106114805750670de0b6b3a764000092915050565b5f4282604001510390508063ffffffff1682602001516001600160801b03166114a991906140f4565b6114bb90670de0b6b3a7640000614132565b949350505050565b6060600180546107b590614041565b600b5463ffffffff9081165f908152600a6020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001015480851691830191909152600160201b90049092166060830152906115378184612bbd565b9392505050565b610868338383612cd2565b611553848361294a565b610e2684848484612d70565b611567612892565b61156f6128eb565b808042111561159157604051631ab7da6b60e01b815260040160405180910390fd5b60028310156115b35760405163162908e360e11b815260040160405180910390fd5b5f80805b858110156116bc57336115e18888848181106115d5576115d5614079565b905060200201356113af565b6001600160a01b031614611608576040516359dc379f60e01b815260040160405180910390fd5b5f60085f89898581811061161e5761161e614079565b602090810292909201358352508181019290925260409081015f20815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b9004909116606082015291506116919085614145565b93508263ffffffff16816040015163ffffffff1611156116b357806040015192505b506001016115b7565b505f6116c84283614164565b905062ed4e0063ffffffff821611156116f457604051637616640160e01b815260040160405180910390fd5b5f62ed4e00611713670de0b6b3a7640000673782dace9d9000006140d5565b6001600160801b0316856001600160801b031661173091906140f4565b61173a919061411f565b90506001600160801b038111156117645760405163162908e360e11b815260040160405180910390fd5b6007805482915f9160159061178590600160a81b900463ffffffff16614180565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff1690506117b43382612d88565b5f5b8981101561189f575f8b8b838181106117d1576117d1614079565b602090810292909201355f818152600884526040808220815160808101835281546001600160801b038082168352600160801b909104168188015260019091015463ffffffff808216838501908152600160201b90920481166060840152835180850185528351600f0b8152915116818801528251808401909352838352958201929092529194509291506118699084908390612931565b5f838152600860205260408120908155600101805467ffffffffffffffff1916905561189483612a9a565b5050506001016117b6565b50604080518082018252600f88900b815263ffffffff871660208083019190915282518084019093525f80845290830152906118dd90839083612931565b6040518060800160405280886001600160801b03168152602001846001600160801b031681526020018763ffffffff1681526020014263ffffffff1681525060085f8481526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055509050508a8a905060095f336001600160a01b03166001600160a01b031681526020019081526020015f205f9054906101000a900460ff160360010160095f336001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081336001600160a01b03167fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f85978289349548989604051611a9b9291906001600160801b0392909216825263ffffffff16602082015260400190565b60405180910390a35050505050505050610e416001600655565b611abd612892565b611ac56128eb565b8180421115611ae757604051631ab7da6b60e01b815260040160405180910390fd5b33611af1866113af565b6001600160a01b031614611b18576040516359dc379f60e01b815260040160405180910390fd5b836001600160801b03165f03611b415760405163162908e360e11b815260040160405180910390fd5b5f858152600860209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b900490911660608201529103611bbc57604051632254ea3d60e11b815260040160405180910390fd5b806040015163ffffffff164263ffffffff1610611bec5760405163342ad40160e11b815260040160405180910390fd5b5f428260400151611bfd9190614164565b90505f86835f0151611c0f9190614145565b90505f611c1c82846120e3565b9050856001600160801b0316816001600160801b03161015611c5157604051638199f5f360e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611cb5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd991906141a4565b9050611d196001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633306001600160801b038d16612da1565b611d2c6001600160801b038a1682614132565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611d8e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611db291906141a4565b14611dd0576040516312171d8360e31b815260040160405180910390fd5b6040805180820182528651600f90810b8252878301805163ffffffff908116602080860191909152855180870187529389900b8452915116828201525f8e815260089091529290922080546001600160801b0319166001600160801b0387161790559062ed4e00611e51670de0b6b3a7640000673782dace9d9000006140d5565b6001600160801b0316866001600160801b0316611e6e91906140f4565b611e78919061411f565b5f8d815260086020526040902080546001600160801b03928316600160801b029216919091178155600101805463ffffffff4216600160201b0267ffffffff0000000019909116179055611ecd8c8383612931565b604080516001600160801b038d81168252878116602083015286168183015290518d9133917f1381e2f7d0d4b71a58d34dc3db2051dd52769766e65eabf380c9b4ea93f0890b9181900360600190a35050505050505050610e266001600655565b611f36612b31565b6011805460ff60a01b1916600160a01b179055611f51612dda565b6011546040516001600160a01b0390911681527fc0a1c7e9f05b4d536e1ff8606bae9b847cdb43ef4a9b2d7a503a88cee08dccdb906020015b60405180910390a1565b5f818152600260205260409020546060906001600160a01b0316611fca57604051626f708760e21b815260040160405180910390fd5b600f546001600160a01b0316611ff3576040516338a69c8d60e21b815260040160405180910390fd5b600f54604051602481018490525f9182916001600160a01b039091169060440160408051601f198184030181529181526020820180516001600160e01b031663c87b56dd60e01b1790525161204891906141bb565b5f60405180830381855afa9150503d805f8114612080576040519150601f19603f3d011682016040523d82523d5f602084013e612085565b606091505b5091509150816120cf5760405162461bcd60e51b8152602060048201526015602482015274105c9d081c1c9bde1e4818d85b1b0819985a5b1959605a1b604482015260640161124e565b808060200190518101906114bb91906141d1565b5f63ffffffff821615806120ff575062ed4e0063ffffffff8316115b1561211d57604051637616640160e01b815260040160405180910390fd5b826001600160801b03165f036121465760405163162908e360e11b815260040160405180910390fd5b5f62ed4e00612165670de0b6b3a7640000673782dace9d9000006140d5565b6001600160801b0316856001600160801b031661218291906140f4565b61218c919061411f565b90506001600160801b038111156121b65760405163162908e360e11b815260040160405180910390fd5b805f6121d163ffffffff86166001600160801b0384166140f4565b90505f6121e682670de0b6b3a7640000614132565b9050673782dace9d90000081111561221157604051638f651fb760e01b815260040160405180910390fd5b670de0b6b3a764000081101561223a57604051631bc4bcf760e21b815260040160405180910390fd5b9695505050505050565b5f828152600c602052604081205463ffffffff16808203612268575f9150506107a1565b5f848152600d6020908152604080832063ffffffff80861685529083529281902081516080810183528154600f81810b8352600160801b909104900b9381019390935260010154808416918301829052600160201b90049092166060820152906122d29085614164565b63ffffffff1681602001516122e79190614246565b815182906122f690839061426c565b600f90810b90915282515f910b1215905061230f575f81525b516001600160801b0316949350505050565b600f545f90819063ffffffff600160a01b909104811690841611612345578261235f565b600f5461235f90600160a01b900463ffffffff1684614164565b90505f62ed4e00612380670de0b6b3a7640000673782dace9d9000006140d5565b6001600160801b0316866001600160801b031661239d91906140f4565b6123a7919061411f565b9050806123c363ffffffff84166001600160801b0383166140f4565b61223a90670de0b6b3a7640000614132565b5f6123de612892565b6123e66128eb565b828042111561240857604051631ab7da6b60e01b815260040160405180910390fd5b856001600160801b03165f036124315760405163162908e360e11b815260040160405180910390fd5b63ffffffff8516158061244c575062ed4e0063ffffffff8616115b1561246a57604051637616640160e01b815260040160405180910390fd5b335f90815260096020526040902054606460ff9091161061249e5760405163133cbc4f60e01b815260040160405180910390fd5b5f6124a986426140b9565b90505f5f6124b8898988612e2f565b915091505f60405180604001604052808b600f0b81526020018563ffffffff1681525090506125055f60405180604001604052805f600f0b81526020015f63ffffffff1681525083612931565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612569573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061258d91906141a4565b90506125cd6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633306001600160801b038f16612da1565b6125e06001600160801b038c1682614132565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612642573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061266691906141a4565b14612684576040516312171d8360e31b815260040160405180910390fd5b60078054600163ffffffff600160a81b80840482168381019092160263ffffffff60a81b1990931692909217909255335f818152600960205260409020805460ff80821690950190941660ff199094169390931790925597506126e79088612d88565b604080516080810182526001600160801b03808e168252868116602080840191825263ffffffff808b16858701908152428216606087019081525f8f8152600890945296909220945192518416600160801b0292909316919091178355516001909201805493518216600160201b0267ffffffffffffffff19909416929091169190911791909117905561277b8b84612f0d565b604080516001600160801b038d16815263ffffffff87166020820152889133917fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f8597828934954910160405180910390a35050505050506114bb6001600655565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b61280b612b31565b6001600160a01b03811661283457604051631e4fbdf760e01b81525f600482015260240161124e565b61118b81612b64565b612845612b31565b61140f612fe7565b5f818152600260205260408120546001600160a01b0316806107a157604051637e27328960e01b81526004810184905260240161124e565b610e418383836001613020565b6002600654036128e45760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161124e565b6002600655565b60075460ff161561140f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161124e565b612939613124565b8215610e4157610e41838383613296565b6001600160a01b0382161580159061298a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615155b156108685760405163379607f560e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063379607f5906024016020604051808303815f875af11580156129f3573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e4191906141a4565b6001600160a01b038216612a4057604051633250574960e11b81525f600482015260240161124e565b5f612a4c83833361348c565b9050836001600160a01b0316816001600160a01b031614610e26576040516364283d7b60e01b81526001600160a01b038086166004830152602482018490528216604482015260640161124e565b5f612aa65f835f61348c565b90506001600160a01b03811661086857604051637e27328960e01b81526004810183905260240161124e565b6040516001600160a01b03838116602483015260448201839052610e4191859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061357e565b6007546001600160a01b0361010090910416331461140f5760405163118cdaa760e01b815233600482015260240161124e565b600780546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f5f8390505f62093a80808360400151612bd79190614299565b612be191906142c0565b90505f5b60ff811015612cad57612bfb62093a80836140b9565b91505f63ffffffff8087169084161115612c1757859250612c31565b5063ffffffff82165f908152600e6020526040902054600f0b5b6040840151612c409084614164565b63ffffffff168460200151612c559190614246565b84518590612c6490839061426c565b600f0b90525063ffffffff80871690841603612c805750612cad565b8084602001818151612c9291906142df565b600f0b9052505063ffffffff82166040840152600101612be5565b505f825f0151600f0b1215612cc0575f82525b50516001600160801b03169392505050565b6001600160a01b038216612d0457604051630b61174360e31b81526001600160a01b038316600482015260240161124e565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b612d7b848484610e2c565b610e2633858585856135ea565b610868828260405180602001604052805f815250613712565b6040516001600160a01b038481166024830152838116604483015260648201839052610e269186918216906323b872dd90608401612aff565b612de26128eb565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612e173390565b6040516001600160a01b039091168152602001611f8a565b5f808062ed4e00612e50670de0b6b3a7640000673782dace9d9000006140d5565b6001600160801b0316876001600160801b0316612e6d91906140f4565b612e77919061411f565b90506001600160801b03811115612ea15760405163162908e360e11b815260040160405180910390fd5b915081612ebd63ffffffff86166001600160801b0383166140f4565b612ecf90670de0b6b3a7640000614132565b9150836001600160801b0316826001600160801b03161015612f0457604051638199f5f360e01b815260040160405180910390fd5b50935093915050565b5f612f246001600160801b038084169085166140f4565b9050816001600160801b0316836001600160801b031682612f45919061411f565b14612f6357604051630fc12e3560e11b815260040160405180910390fd5b5f612f76670de0b6b3a76400008361411f565b90506001600160801b03811115612fa05760405163162908e360e11b815260040160405180910390fd5b601080548291905f90612fbd9084906001600160801b0316614145565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555050505050565b612fef613729565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612e17565b808061303457506001600160a01b03821615155b156130f5575f6130438461284d565b90506001600160a01b0383161580159061306f5750826001600160a01b0316816001600160a01b031614155b8015613082575061308081846127d6565b155b156130ab5760405163a9fbf51f60e01b81526001600160a01b038416600482015260240161124e565b81156130f35783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600b5463ffffffff16613156604080516080810182525f80825260208201819052918101829052606081019190915290565b63ffffffff8216156131cf57600a5f613170600185614164565b63ffffffff908116825260208083019390935260409182015f2082516080810184528154600f81810b8352600160801b909104900b948101949094526001015480821692840192909252600160201b90910416606082015290506131fc565b50604080516080810182525f808252602082015263ffffffff428116928201929092524390911660608201525b60408101515f63ffffffff80831642909116111561325d5760408301516132299063ffffffff164261430c565b606084015161323e9063ffffffff164361430c565b61325090670de0b6b3a76400006140f4565b61325a919061411f565b90505b61326983838387613772565b92506132768460016140b9565b600b805463ffffffff191663ffffffff9290921691909117905550505050565b604080516080810182525f808252602082018190529181018290526060810191909152604080516080810182525f8082526020820181905291810182905260608101919091524263ffffffff16846020015163ffffffff1611801561330057505f845f0151600f0b135b1561334a5783516133159062ed4e009061431f565b600f0b60208084019190915284015161332f904290614164565b63ffffffff1682602001516133449190614246565b600f0b82525b4263ffffffff16836020015163ffffffff1611801561336e57505f835f0151600f0b135b156133b85782516133839062ed4e009061431f565b600f0b60208083019190915283015161339d904290614164565b63ffffffff1681602001516133b29190614246565b600f0b81525b6133cc848484602001518460200151613977565b5f858152600c60205260408120546133eb9063ffffffff1660016140b9565b5f878152600c60209081526040808320805463ffffffff95861663ffffffff199091168117909155428516878301908152438616606089019081529b8552600d84528285209185529083529220855195909101516001600160801b03908116600160801b02951694909417845551600193909301805497518216600160201b0267ffffffffffffffff19909816939091169290921795909517905550505050565b5f828152600260205260408120546001600160a01b03908116908316156134b8576134b8818486613ab2565b6001600160a01b038116156134f2576134d35f855f5f613020565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b03851615613520576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b5f5f60205f8451602086015f885af18061359d576040513d5f823e3d81fd5b50505f513d915081156135b45780600114156135c1565b6001600160a01b0384163b155b15610e2657604051635274afe760e01b81526001600160a01b038516600482015260240161124e565b6001600160a01b0383163b1561370b57604051630a85bd0160e11b81526001600160a01b0384169063150b7a029061362c90889088908790879060040161435b565b6020604051808303815f875af1925050508015613666575060408051601f3d908101601f191682019092526136639181019061438d565b60015b6136cd573d808015613693576040519150601f19603f3d011682016040523d82523d5f602084013e613698565b606091505b5080515f036136c557604051633250574960e11b81526001600160a01b038516600482015260240161124e565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b1461370957604051633250574960e11b81526001600160a01b038516600482015260240161124e565b505b5050505050565b61371c8383613b16565b610e41335f8585856135ea565b60075460ff1661140f5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161124e565b604080516080810182525f808252602082018190529181018290526060810191909152845f62093a806137a58188614299565b6137af91906142c0565b90505f5b60ff81101561396b576137c962093a80836140b9565b91505f63ffffffff42811690841611156137e5574292506137ff565b5063ffffffff82165f908152600e6020526040902054600f0b5b6138098884614164565b63ffffffff16896020015161381e9190614246565b89518a9061382d90839061426c565b600f0b9052506020890180518291906138479083906142df565b600f0b90525063ffffffff83166040808b0191909152840151670de0b6b3a7640000906138749085614164565b61388d9063ffffffff166001600160801b038a166140f4565b613897919061411f565b846060015163ffffffff166138ac9190614132565b63ffffffff90811660608b0152428116908416036138d6575063ffffffff4316606089015261396b565b88600a5f846138e68a60016140b9565b6138f091906140b9565b63ffffffff908116825260208083019390935260409182015f208451938501516001600160801b03908116600160801b02941693909317835590830151600190920180546060909401518216600160201b0267ffffffffffffffff1990941692909116919091179190911790555090955085906001016137b3565b50959695505050505050565b4263ffffffff16846020015163ffffffff161115613a185760208085015163ffffffff165f908152600e9091526040902054600f0b6139b683826142df565b9050846020015163ffffffff16846020015163ffffffff16036139e0576139dd828261426c565b90505b60208581015163ffffffff165f908152600e9091526040902080546001600160801b0319166001600160801b03929092169190911790555b4263ffffffff16836020015163ffffffff161115610e2657836020015163ffffffff16836020015163ffffffff161115610e265760208084015163ffffffff165f908152600e9091526040902054600f0b613a73828261426c565b60208086015163ffffffff165f908152600e9091526040902080546001600160801b039092166001600160801b03199092169190911790555050505050565b613abd838383613b77565b610e41576001600160a01b038316613aeb57604051637e27328960e01b81526004810182905260240161124e565b60405163177e802f60e01b81526001600160a01b03831660048201526024810182905260440161124e565b6001600160a01b038216613b3f57604051633250574960e11b81525f600482015260240161124e565b5f613b4b83835f61348c565b90506001600160a01b03811615610e41576040516339e3563760e11b81525f600482015260240161124e565b5f6001600160a01b038316158015906114bb5750826001600160a01b0316846001600160a01b03161480613bb05750613bb084846127d6565b806114bb5750505f908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b03198116811461118b575f5ffd5b5f60208284031215613bfd575f5ffd5b813561153781613bd8565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6115376020830184613c08565b5f60208284031215613c58575f5ffd5b5035919050565b80356001600160a01b0381168114613c75575f5ffd5b919050565b5f5f60408385031215613c8b575f5ffd5b613c9483613c5f565b946020939093013593505050565b5f60208284031215613cb2575f5ffd5b61153782613c5f565b602080825282518282018190525f918401906040840190835b81811015613cf2578351835260209384019390920191600101613cd4565b509095945050505050565b803563ffffffff81168114613c75575f5ffd5b5f5f60408385031215613d21575f5ffd5b82359150613d3160208401613cfd565b90509250929050565b80356001600160801b0381168114613c75575f5ffd5b5f5f5f5f60808587031215613d63575f5ffd5b84359350613d7360208601613cfd565b925060408501359150613d8860608601613d3a565b905092959194509250565b5f5f5f60608486031215613da5575f5ffd5b613dae84613c5f565b9250613dbc60208501613c5f565b929592945050506040919091013590565b5f60208284031215613ddd575f5ffd5b61153782613cfd565b5f5f60408385031215613df7575f5ffd5b613e0083613c5f565b915060208301358015158114613e14575f5ffd5b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613e5c57613e5c613e1f565b604052919050565b5f67ffffffffffffffff821115613e7d57613e7d613e1f565b50601f01601f191660200190565b5f5f5f5f60808587031215613e9e575f5ffd5b613ea785613c5f565b9350613eb560208601613c5f565b925060408501359150606085013567ffffffffffffffff811115613ed7575f5ffd5b8501601f81018713613ee7575f5ffd5b8035613efa613ef582613e64565b613e33565b818152886020838501011115613f0e575f5ffd5b816020840160208301375f6020838301015280935050505092959194509250565b5f5f5f60408486031215613f41575f5ffd5b833567ffffffffffffffff811115613f57575f5ffd5b8401601f81018613613f67575f5ffd5b803567ffffffffffffffff811115613f7d575f5ffd5b8660208260051b8401011115613f91575f5ffd5b6020918201979096509401359392505050565b5f5f5f5f60808587031215613fb7575f5ffd5b84359350613d7360208601613d3a565b5f5f60408385031215613fd8575f5ffd5b613fe183613d3a565b9150613d3160208401613cfd565b5f5f5f5f60808587031215614002575f5ffd5b61400b85613d3a565b9350613d7360208601613cfd565b5f5f6040838503121561402a575f5ffd5b61403383613c5f565b9150613d3160208401613c5f565b600181811c9082168061405557607f821691505b60208210810361407357634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016140b2576140b261408d565b5060010190565b63ffffffff81811683821601908111156107a1576107a161408d565b6001600160801b0382811682821603908111156107a1576107a161408d565b80820281158282048414176107a1576107a161408d565b634e487b7160e01b5f52601260045260245ffd5b5f8261412d5761412d61410b565b500490565b808201808211156107a1576107a161408d565b6001600160801b0381811683821601908111156107a1576107a161408d565b63ffffffff82811682821603908111156107a1576107a161408d565b5f63ffffffff821663ffffffff810361419b5761419b61408d565b60010192915050565b5f602082840312156141b4575f5ffd5b5051919050565b5f82518060208501845e5f920191825250919050565b5f602082840312156141e1575f5ffd5b815167ffffffffffffffff8111156141f7575f5ffd5b8201601f81018413614207575f5ffd5b8051614215613ef582613e64565b818152856020838501011115614229575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f82600f0b82600f0b0280600f0b91508082146142655761426561408d565b5092915050565b600f82810b9082900b0360016001607f1b0319811260016001607f1b03821317156107a1576107a161408d565b5f63ffffffff8316806142ae576142ae61410b565b8063ffffffff84160491505092915050565b63ffffffff81811683821602908116908181146142655761426561408d565b600f81810b9083900b0160016001607f1b03811360016001607f1b0319821217156107a1576107a161408d565b818103818111156107a1576107a161408d565b5f81600f0b83600f0b806143355761433561410b565b60016001607f1b031982145f19821416156143525761435261408d565b90059392505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f9061223a90830184613c08565b5f6020828403121561439d575f5ffd5b815161153781613bd856fea26469706673582212203b6888d2732bfd5dcfd7dcb20ed792bd78ab3c61911802ab6ecfffddb0d6307664736f6c634300081b00330000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a000000000000000000000000854364fd5853cf618954753cd269d2d7af580c7a0000000000000000000000005e4d8755c0cbd26e8670b27bc0bd21ef84cd881d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000854657374206e66740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003544e540000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610260575f3560e01c80638b25e8c11161014b578063beb83109116100bf578063df0c78ef11610084578063df0c78ef146106dd578063df215157146106f0578063e58f594714610703578063e985e9c514610728578063f2fde38b1461073b578063f7b188a51461074e575f5ffd5b8063beb8310914610689578063c5b1c7d01461069c578063c87b56dd146106a4578063d89dd269146106b7578063ddacc94a146106ca575f5ffd5b806397612d4b1161011057806397612d4b146105de5780639b7d02ad146105f1578063a22cb4651461062e578063b88d4fde14610641578063bbe33ea514610654578063bcc0022514610667575f5ffd5b80638b25e8c1146105415780638da5cb5b146105545780638ff424901461056a578063900cf0cf146105b157806395d89b41146105d6575f5ffd5b80632e1a7d4d116101e2578063586c2600116101a7578063586c2600146104425780635c975abb146104775780636352211e1461048257806370a0823114610495578063715018a6146104b657806389f839c6146104be575f5ffd5b80632e1a7d4d146103e35780632e720f7d146103f657806342842e0e146104095780635312ea8e1461041c5780635594a0451461042f575f5ffd5b80631d237a49116102285780631d237a49146103015780631f5ab0221461038657806320a194b81461039957806323b872dd146103ab578063268dc199146103be575f5ffd5b806301ffc9a71461026457806306fdde031461028c578063081812fc146102a1578063095ea7b3146102cc57806313de148b146102e1575b5f5ffd5b610277610272366004613bed565b610756565b60405190151581526020015b60405180910390f35b6102946107a7565b6040516102839190613c36565b6102b46102af366004613c48565b610836565b6040516001600160a01b039091168152602001610283565b6102df6102da366004613c7a565b61085d565b005b6102f46102ef366004613ca2565b61086c565b6040516102839190613cbb565b61035361030f366004613d10565b600d60209081525f928352604080842090915290825290208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b60408051600f95860b81529390940b602084015263ffffffff918216938301939093529091166060820152608001610283565b6102df610394366004613d50565b610960565b601154600160a01b900460ff16610277565b6102df6103b9366004613d93565b610e2c565b6010546001600160801b03165b6040516001600160801b039091168152602001610283565b6102df6103f1366004613c48565b610e46565b6102df610404366004613ca2565b61118e565b6102df610417366004613d93565b6111df565b6102df61042a366004613c48565b6111f9565b600f546102b4906001600160a01b031681565b610464610450366004613dcd565b600e6020525f9081526040902054600f0b81565b604051600f9190910b8152602001610283565b60075460ff16610277565b6102b4610490366004613c48565b6113af565b6104a86104a3366004613ca2565b6113b9565b604051908152602001610283565b6102df6113fe565b61050a6104cc366004613c48565b60086020525f9081526040902080546001909101546001600160801b0380831692600160801b9004169063ffffffff80821691600160201b90041684565b604080516001600160801b03958616815294909316602085015263ffffffff91821692840192909252166060820152608001610283565b6103cb61054f366004613c48565b611411565b60075461010090046001600160a01b03166102b4565b610353610578366004613dcd565b600a6020525f908152604090208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b600b546105c19063ffffffff1681565b60405163ffffffff9091168152602001610283565b6102946114c3565b6103cb6105ec366004613dcd565b6114d2565b61061c6105ff366004613ca2565b6001600160a01b03165f9081526009602052604090205460ff1690565b60405160ff9091168152602001610283565b6102df61063c366004613de6565b61153e565b6102df61064f366004613e8b565b611549565b6102df610662366004613f2f565b61155f565b61061c610675366004613ca2565b60096020525f908152604090205460ff1681565b6102df610697366004613fa4565b611ab5565b6102df611f2e565b6102946106b2366004613c48565b611f94565b6103cb6106c5366004613fc7565b6120e3565b6103cb6106d8366004613d10565b612244565b6103cb6106eb366004613fc7565b612321565b6104a86106fe366004613fef565b6123d5565b6105c1610711366004613c48565b600c6020525f908152604090205463ffffffff1681565b610277610736366004614019565b6127d6565b6102df610749366004613ca2565b612803565b6102df61283d565b5f6001600160e01b031982166380ac58cd60e01b148061078657506001600160e01b03198216635b5e139f60e01b145b806107a157506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f80546107b590614041565b80601f01602080910402602001604051908101604052809291908181526020018280546107e190614041565b801561082c5780601f106108035761010080835404028352916020019161082c565b820191905f5260205f20905b81548152906001019060200180831161080f57829003601f168201915b5050505050905090565b5f6108408261284d565b505f828152600460205260409020546001600160a01b03166107a1565b610868828233612885565b5050565b6001600160a01b0381165f9081526009602052604090205460609060ff168067ffffffffffffffff8111156108a3576108a3613e1f565b6040519080825280602002602001820160405280156108cc578160200160208202803683370190505b5091508060ff165f036108df5750919050565b5f805b600754600160a81b900463ffffffff16811015610958575f818152600260205260409020546001600160a01b03868116911603610950578084838151811061092c5761092c614079565b602090810291909101015281610941816140a1565b9250508260ff16821015610958575b6001016108e2565b505050919050565b610968612892565b6109706128eb565b818042111561099257604051631ab7da6b60e01b815260040160405180910390fd5b3361099c866113af565b6001600160a01b0316146109c3576040516359dc379f60e01b815260040160405180910390fd5b5f858152600860209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b900490911660608201529103610a3e57604051632254ea3d60e11b815260040160405180910390fd5b806040015163ffffffff164263ffffffff1610610a6e5760405163342ad40160e11b815260040160405180910390fd5b5f610a7986426140b9565b905063ffffffff86161580610aa55750610a9662ed4e00426140b9565b63ffffffff168163ffffffff16115b15610ac357604051637616640160e01b815260040160405180910390fd5b5f62ed4e00610ae2670de0b6b3a7640000673782dace9d9000006140d5565b8451610afa916001600160801b0390811691166140f4565b610b04919061411f565b90506001600160801b03811115610b2e5760405163162908e360e11b815260040160405180910390fd5b805f610b4963ffffffff8a166001600160801b0384166140f4565b610b5b90670de0b6b3a7640000614132565b9050866001600160801b0316816001600160801b03161015610b9057604051638199f5f360e01b815260040160405180910390fd5b673782dace9d9000006001600160801b0382161115610bc257604051638f651fb760e01b815260040160405180910390fd5b5f6040518060400160405280875f0151600f0b8152602001876040015163ffffffff1681525090505f6040518060400160405280885f0151600f0b81526020018763ffffffff1681525090506040518060800160405280885f01516001600160801b03168152602001856001600160801b031681526020018763ffffffff1681526020014263ffffffff1681525060085f8e81526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055509050505f670de0b6b3a76400006001600160801b0316610d238e611411565b8951610d3b916001600160801b0390811691166140f4565b610d45919061411f565b88519091505f90670de0b6b3a764000090610d6c906001600160801b0388811691166140f4565b610d76919061411f565b6010549091508190610d929084906001600160801b03166140d5565b610d9c9190614145565b601080546001600160801b0319166001600160801b0392909216919091179055610dc78e8585612931565b6040805163ffffffff8a1681526001600160801b03871660208201528f9133917f3032be442129e161b4ae1cdee94871a69de2c16ee2007f31fc209a715673455c910160405180910390a350505050505050505050610e266001600655565b50505050565b610e36838261294a565b610e41838383612a17565b505050565b610e4e612892565b5f818152600260205260409020546001600160a01b031680610e8257604051626f708760e21b815260040160405180910390fd5b6001600160a01b0381163314610eab576040516359dc379f60e01b815260040160405180910390fd5b5f828152600860209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b900490911660608201529103610f2657604051632254ea3d60e11b815260040160405180910390fd5b806040015163ffffffff164263ffffffff161015610f575760405163342ad40160e11b815260040160405180910390fd5b8051604080518082018252600f83900b81528184015163ffffffff166020808301919091525f8781526008909152918220828155600101805467ffffffffffffffff1916905590610fa786611411565b90505f670de0b6b3a7640000610fc96001600160801b038085169087166140f4565b610fd3919061411f565b9050816001600160801b0316846001600160801b031682610ff4919061411f565b1461101257604051630fc12e3560e11b815260040160405180910390fd5b5f611025670de0b6b3a76400008361411f565b90506001600160801b0381111561104f5760405163162908e360e11b815260040160405180910390fd5b601080548291905f9061106c9084906001600160801b03166140d5565b92506101000a8154816001600160801b0302191690836001600160801b031602179055506110b8888560405180604001604052805f600f0b81526020015f63ffffffff16815250612931565b5f888152600c60205260409020805463ffffffff191690556110d988612a9a565b335f818152600960205260409020805460ff19811660ff9182165f190190911617905561113a906001600160a01b037f0000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a16906001600160801b038816612ad2565b6040516001600160801b0386168152889033907f8903a5b5d08a841e7f68438387f1da20c84dea756379ed37e633ff3854b99b849060200160405180910390a35050505050505061118b6001600655565b50565b611196612b31565b6001600160a01b0381166111bd5760405163d92e233d60e01b815260040160405180910390fd5b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b610e4183838360405180602001604052805f815250611549565b611201612892565b601154600160a01b900460ff166112575760405162461bcd60e51b81526020600482015260156024820152744e6f7420696e20656d657267656e6379206d6f646560581b60448201526064015b60405180910390fd5b33611261826113af565b6001600160a01b031614611288576040516359dc379f60e01b815260040160405180910390fd5b5f818152600860208181526040808420815160808101835281546001600160801b03808216808452600160801b909204168286015260018301805463ffffffff80821696850196909652600160201b810490951660608401528888529590945294905567ffffffffffffffff191690915561130283612a9a565b335f818152600960205260409020805460ff19811660ff9182165f1901909116179055611363906001600160a01b037f0000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a16906001600160801b038416612ad2565b6040516001600160801b0382168152839033907f4f27eb511b2a4633cfb633ac1c4a99b4c298ca6488b29ec26f3504a5927f67289060200160405180910390a3505061118b6001600655565b5f6107a18261284d565b5f6001600160a01b0382166113e3576040516322718ad960e21b81525f600482015260240161124e565b506001600160a01b03165f9081526003602052604090205490565b611406612b31565b61140f5f612b64565b565b5f818152600860209081526040808320815160808101835281546001600160801b038082168352600160801b90910416938101939093526001015463ffffffff808216928401839052600160201b909104811660608401524216106114805750670de0b6b3a764000092915050565b5f4282604001510390508063ffffffff1682602001516001600160801b03166114a991906140f4565b6114bb90670de0b6b3a7640000614132565b949350505050565b6060600180546107b590614041565b600b5463ffffffff9081165f908152600a6020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001015480851691830191909152600160201b90049092166060830152906115378184612bbd565b9392505050565b610868338383612cd2565b611553848361294a565b610e2684848484612d70565b611567612892565b61156f6128eb565b808042111561159157604051631ab7da6b60e01b815260040160405180910390fd5b60028310156115b35760405163162908e360e11b815260040160405180910390fd5b5f80805b858110156116bc57336115e18888848181106115d5576115d5614079565b905060200201356113af565b6001600160a01b031614611608576040516359dc379f60e01b815260040160405180910390fd5b5f60085f89898581811061161e5761161e614079565b602090810292909201358352508181019290925260409081015f20815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b9004909116606082015291506116919085614145565b93508263ffffffff16816040015163ffffffff1611156116b357806040015192505b506001016115b7565b505f6116c84283614164565b905062ed4e0063ffffffff821611156116f457604051637616640160e01b815260040160405180910390fd5b5f62ed4e00611713670de0b6b3a7640000673782dace9d9000006140d5565b6001600160801b0316856001600160801b031661173091906140f4565b61173a919061411f565b90506001600160801b038111156117645760405163162908e360e11b815260040160405180910390fd5b6007805482915f9160159061178590600160a81b900463ffffffff16614180565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff1690506117b43382612d88565b5f5b8981101561189f575f8b8b838181106117d1576117d1614079565b602090810292909201355f818152600884526040808220815160808101835281546001600160801b038082168352600160801b909104168188015260019091015463ffffffff808216838501908152600160201b90920481166060840152835180850185528351600f0b8152915116818801528251808401909352838352958201929092529194509291506118699084908390612931565b5f838152600860205260408120908155600101805467ffffffffffffffff1916905561189483612a9a565b5050506001016117b6565b50604080518082018252600f88900b815263ffffffff871660208083019190915282518084019093525f80845290830152906118dd90839083612931565b6040518060800160405280886001600160801b03168152602001846001600160801b031681526020018763ffffffff1681526020014263ffffffff1681525060085f8481526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055509050508a8a905060095f336001600160a01b03166001600160a01b031681526020019081526020015f205f9054906101000a900460ff160360010160095f336001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081336001600160a01b03167fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f85978289349548989604051611a9b9291906001600160801b0392909216825263ffffffff16602082015260400190565b60405180910390a35050505050505050610e416001600655565b611abd612892565b611ac56128eb565b8180421115611ae757604051631ab7da6b60e01b815260040160405180910390fd5b33611af1866113af565b6001600160a01b031614611b18576040516359dc379f60e01b815260040160405180910390fd5b836001600160801b03165f03611b415760405163162908e360e11b815260040160405180910390fd5b5f858152600860209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b900490911660608201529103611bbc57604051632254ea3d60e11b815260040160405180910390fd5b806040015163ffffffff164263ffffffff1610611bec5760405163342ad40160e11b815260040160405180910390fd5b5f428260400151611bfd9190614164565b90505f86835f0151611c0f9190614145565b90505f611c1c82846120e3565b9050856001600160801b0316816001600160801b03161015611c5157604051638199f5f360e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f907f0000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a6001600160a01b0316906370a0823190602401602060405180830381865afa158015611cb5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd991906141a4565b9050611d196001600160a01b037f0000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a1633306001600160801b038d16612da1565b611d2c6001600160801b038a1682614132565b6040516370a0823160e01b81523060048201527f0000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a6001600160a01b0316906370a0823190602401602060405180830381865afa158015611d8e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611db291906141a4565b14611dd0576040516312171d8360e31b815260040160405180910390fd5b6040805180820182528651600f90810b8252878301805163ffffffff908116602080860191909152855180870187529389900b8452915116828201525f8e815260089091529290922080546001600160801b0319166001600160801b0387161790559062ed4e00611e51670de0b6b3a7640000673782dace9d9000006140d5565b6001600160801b0316866001600160801b0316611e6e91906140f4565b611e78919061411f565b5f8d815260086020526040902080546001600160801b03928316600160801b029216919091178155600101805463ffffffff4216600160201b0267ffffffff0000000019909116179055611ecd8c8383612931565b604080516001600160801b038d81168252878116602083015286168183015290518d9133917f1381e2f7d0d4b71a58d34dc3db2051dd52769766e65eabf380c9b4ea93f0890b9181900360600190a35050505050505050610e266001600655565b611f36612b31565b6011805460ff60a01b1916600160a01b179055611f51612dda565b6011546040516001600160a01b0390911681527fc0a1c7e9f05b4d536e1ff8606bae9b847cdb43ef4a9b2d7a503a88cee08dccdb906020015b60405180910390a1565b5f818152600260205260409020546060906001600160a01b0316611fca57604051626f708760e21b815260040160405180910390fd5b600f546001600160a01b0316611ff3576040516338a69c8d60e21b815260040160405180910390fd5b600f54604051602481018490525f9182916001600160a01b039091169060440160408051601f198184030181529181526020820180516001600160e01b031663c87b56dd60e01b1790525161204891906141bb565b5f60405180830381855afa9150503d805f8114612080576040519150601f19603f3d011682016040523d82523d5f602084013e612085565b606091505b5091509150816120cf5760405162461bcd60e51b8152602060048201526015602482015274105c9d081c1c9bde1e4818d85b1b0819985a5b1959605a1b604482015260640161124e565b808060200190518101906114bb91906141d1565b5f63ffffffff821615806120ff575062ed4e0063ffffffff8316115b1561211d57604051637616640160e01b815260040160405180910390fd5b826001600160801b03165f036121465760405163162908e360e11b815260040160405180910390fd5b5f62ed4e00612165670de0b6b3a7640000673782dace9d9000006140d5565b6001600160801b0316856001600160801b031661218291906140f4565b61218c919061411f565b90506001600160801b038111156121b65760405163162908e360e11b815260040160405180910390fd5b805f6121d163ffffffff86166001600160801b0384166140f4565b90505f6121e682670de0b6b3a7640000614132565b9050673782dace9d90000081111561221157604051638f651fb760e01b815260040160405180910390fd5b670de0b6b3a764000081101561223a57604051631bc4bcf760e21b815260040160405180910390fd5b9695505050505050565b5f828152600c602052604081205463ffffffff16808203612268575f9150506107a1565b5f848152600d6020908152604080832063ffffffff80861685529083529281902081516080810183528154600f81810b8352600160801b909104900b9381019390935260010154808416918301829052600160201b90049092166060820152906122d29085614164565b63ffffffff1681602001516122e79190614246565b815182906122f690839061426c565b600f90810b90915282515f910b1215905061230f575f81525b516001600160801b0316949350505050565b600f545f90819063ffffffff600160a01b909104811690841611612345578261235f565b600f5461235f90600160a01b900463ffffffff1684614164565b90505f62ed4e00612380670de0b6b3a7640000673782dace9d9000006140d5565b6001600160801b0316866001600160801b031661239d91906140f4565b6123a7919061411f565b9050806123c363ffffffff84166001600160801b0383166140f4565b61223a90670de0b6b3a7640000614132565b5f6123de612892565b6123e66128eb565b828042111561240857604051631ab7da6b60e01b815260040160405180910390fd5b856001600160801b03165f036124315760405163162908e360e11b815260040160405180910390fd5b63ffffffff8516158061244c575062ed4e0063ffffffff8616115b1561246a57604051637616640160e01b815260040160405180910390fd5b335f90815260096020526040902054606460ff9091161061249e5760405163133cbc4f60e01b815260040160405180910390fd5b5f6124a986426140b9565b90505f5f6124b8898988612e2f565b915091505f60405180604001604052808b600f0b81526020018563ffffffff1681525090506125055f60405180604001604052805f600f0b81526020015f63ffffffff1681525083612931565b6040516370a0823160e01b81523060048201525f907f0000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a6001600160a01b0316906370a0823190602401602060405180830381865afa158015612569573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061258d91906141a4565b90506125cd6001600160a01b037f0000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a1633306001600160801b038f16612da1565b6125e06001600160801b038c1682614132565b6040516370a0823160e01b81523060048201527f0000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a6001600160a01b0316906370a0823190602401602060405180830381865afa158015612642573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061266691906141a4565b14612684576040516312171d8360e31b815260040160405180910390fd5b60078054600163ffffffff600160a81b80840482168381019092160263ffffffff60a81b1990931692909217909255335f818152600960205260409020805460ff80821690950190941660ff199094169390931790925597506126e79088612d88565b604080516080810182526001600160801b03808e168252868116602080840191825263ffffffff808b16858701908152428216606087019081525f8f8152600890945296909220945192518416600160801b0292909316919091178355516001909201805493518216600160201b0267ffffffffffffffff19909416929091169190911791909117905561277b8b84612f0d565b604080516001600160801b038d16815263ffffffff87166020820152889133917fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f8597828934954910160405180910390a35050505050506114bb6001600655565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b61280b612b31565b6001600160a01b03811661283457604051631e4fbdf760e01b81525f600482015260240161124e565b61118b81612b64565b612845612b31565b61140f612fe7565b5f818152600260205260408120546001600160a01b0316806107a157604051637e27328960e01b81526004810184905260240161124e565b610e418383836001613020565b6002600654036128e45760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161124e565b6002600655565b60075460ff161561140f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161124e565b612939613124565b8215610e4157610e41838383613296565b6001600160a01b0382161580159061298a57507f000000000000000000000000854364fd5853cf618954753cd269d2d7af580c7a6001600160a01b031615155b156108685760405163379607f560e01b8152600481018290527f000000000000000000000000854364fd5853cf618954753cd269d2d7af580c7a6001600160a01b03169063379607f5906024016020604051808303815f875af11580156129f3573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e4191906141a4565b6001600160a01b038216612a4057604051633250574960e11b81525f600482015260240161124e565b5f612a4c83833361348c565b9050836001600160a01b0316816001600160a01b031614610e26576040516364283d7b60e01b81526001600160a01b038086166004830152602482018490528216604482015260640161124e565b5f612aa65f835f61348c565b90506001600160a01b03811661086857604051637e27328960e01b81526004810183905260240161124e565b6040516001600160a01b03838116602483015260448201839052610e4191859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061357e565b6007546001600160a01b0361010090910416331461140f5760405163118cdaa760e01b815233600482015260240161124e565b600780546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f5f8390505f62093a80808360400151612bd79190614299565b612be191906142c0565b90505f5b60ff811015612cad57612bfb62093a80836140b9565b91505f63ffffffff8087169084161115612c1757859250612c31565b5063ffffffff82165f908152600e6020526040902054600f0b5b6040840151612c409084614164565b63ffffffff168460200151612c559190614246565b84518590612c6490839061426c565b600f0b90525063ffffffff80871690841603612c805750612cad565b8084602001818151612c9291906142df565b600f0b9052505063ffffffff82166040840152600101612be5565b505f825f0151600f0b1215612cc0575f82525b50516001600160801b03169392505050565b6001600160a01b038216612d0457604051630b61174360e31b81526001600160a01b038316600482015260240161124e565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b612d7b848484610e2c565b610e2633858585856135ea565b610868828260405180602001604052805f815250613712565b6040516001600160a01b038481166024830152838116604483015260648201839052610e269186918216906323b872dd90608401612aff565b612de26128eb565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612e173390565b6040516001600160a01b039091168152602001611f8a565b5f808062ed4e00612e50670de0b6b3a7640000673782dace9d9000006140d5565b6001600160801b0316876001600160801b0316612e6d91906140f4565b612e77919061411f565b90506001600160801b03811115612ea15760405163162908e360e11b815260040160405180910390fd5b915081612ebd63ffffffff86166001600160801b0383166140f4565b612ecf90670de0b6b3a7640000614132565b9150836001600160801b0316826001600160801b03161015612f0457604051638199f5f360e01b815260040160405180910390fd5b50935093915050565b5f612f246001600160801b038084169085166140f4565b9050816001600160801b0316836001600160801b031682612f45919061411f565b14612f6357604051630fc12e3560e11b815260040160405180910390fd5b5f612f76670de0b6b3a76400008361411f565b90506001600160801b03811115612fa05760405163162908e360e11b815260040160405180910390fd5b601080548291905f90612fbd9084906001600160801b0316614145565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555050505050565b612fef613729565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612e17565b808061303457506001600160a01b03821615155b156130f5575f6130438461284d565b90506001600160a01b0383161580159061306f5750826001600160a01b0316816001600160a01b031614155b8015613082575061308081846127d6565b155b156130ab5760405163a9fbf51f60e01b81526001600160a01b038416600482015260240161124e565b81156130f35783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600b5463ffffffff16613156604080516080810182525f80825260208201819052918101829052606081019190915290565b63ffffffff8216156131cf57600a5f613170600185614164565b63ffffffff908116825260208083019390935260409182015f2082516080810184528154600f81810b8352600160801b909104900b948101949094526001015480821692840192909252600160201b90910416606082015290506131fc565b50604080516080810182525f808252602082015263ffffffff428116928201929092524390911660608201525b60408101515f63ffffffff80831642909116111561325d5760408301516132299063ffffffff164261430c565b606084015161323e9063ffffffff164361430c565b61325090670de0b6b3a76400006140f4565b61325a919061411f565b90505b61326983838387613772565b92506132768460016140b9565b600b805463ffffffff191663ffffffff9290921691909117905550505050565b604080516080810182525f808252602082018190529181018290526060810191909152604080516080810182525f8082526020820181905291810182905260608101919091524263ffffffff16846020015163ffffffff1611801561330057505f845f0151600f0b135b1561334a5783516133159062ed4e009061431f565b600f0b60208084019190915284015161332f904290614164565b63ffffffff1682602001516133449190614246565b600f0b82525b4263ffffffff16836020015163ffffffff1611801561336e57505f835f0151600f0b135b156133b85782516133839062ed4e009061431f565b600f0b60208083019190915283015161339d904290614164565b63ffffffff1681602001516133b29190614246565b600f0b81525b6133cc848484602001518460200151613977565b5f858152600c60205260408120546133eb9063ffffffff1660016140b9565b5f878152600c60209081526040808320805463ffffffff95861663ffffffff199091168117909155428516878301908152438616606089019081529b8552600d84528285209185529083529220855195909101516001600160801b03908116600160801b02951694909417845551600193909301805497518216600160201b0267ffffffffffffffff19909816939091169290921795909517905550505050565b5f828152600260205260408120546001600160a01b03908116908316156134b8576134b8818486613ab2565b6001600160a01b038116156134f2576134d35f855f5f613020565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b03851615613520576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b5f5f60205f8451602086015f885af18061359d576040513d5f823e3d81fd5b50505f513d915081156135b45780600114156135c1565b6001600160a01b0384163b155b15610e2657604051635274afe760e01b81526001600160a01b038516600482015260240161124e565b6001600160a01b0383163b1561370b57604051630a85bd0160e11b81526001600160a01b0384169063150b7a029061362c90889088908790879060040161435b565b6020604051808303815f875af1925050508015613666575060408051601f3d908101601f191682019092526136639181019061438d565b60015b6136cd573d808015613693576040519150601f19603f3d011682016040523d82523d5f602084013e613698565b606091505b5080515f036136c557604051633250574960e11b81526001600160a01b038516600482015260240161124e565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b1461370957604051633250574960e11b81526001600160a01b038516600482015260240161124e565b505b5050505050565b61371c8383613b16565b610e41335f8585856135ea565b60075460ff1661140f5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161124e565b604080516080810182525f808252602082018190529181018290526060810191909152845f62093a806137a58188614299565b6137af91906142c0565b90505f5b60ff81101561396b576137c962093a80836140b9565b91505f63ffffffff42811690841611156137e5574292506137ff565b5063ffffffff82165f908152600e6020526040902054600f0b5b6138098884614164565b63ffffffff16896020015161381e9190614246565b89518a9061382d90839061426c565b600f0b9052506020890180518291906138479083906142df565b600f0b90525063ffffffff83166040808b0191909152840151670de0b6b3a7640000906138749085614164565b61388d9063ffffffff166001600160801b038a166140f4565b613897919061411f565b846060015163ffffffff166138ac9190614132565b63ffffffff90811660608b0152428116908416036138d6575063ffffffff4316606089015261396b565b88600a5f846138e68a60016140b9565b6138f091906140b9565b63ffffffff908116825260208083019390935260409182015f208451938501516001600160801b03908116600160801b02941693909317835590830151600190920180546060909401518216600160201b0267ffffffffffffffff1990941692909116919091179190911790555090955085906001016137b3565b50959695505050505050565b4263ffffffff16846020015163ffffffff161115613a185760208085015163ffffffff165f908152600e9091526040902054600f0b6139b683826142df565b9050846020015163ffffffff16846020015163ffffffff16036139e0576139dd828261426c565b90505b60208581015163ffffffff165f908152600e9091526040902080546001600160801b0319166001600160801b03929092169190911790555b4263ffffffff16836020015163ffffffff161115610e2657836020015163ffffffff16836020015163ffffffff161115610e265760208084015163ffffffff165f908152600e9091526040902054600f0b613a73828261426c565b60208086015163ffffffff165f908152600e9091526040902080546001600160801b039092166001600160801b03199092169190911790555050505050565b613abd838383613b77565b610e41576001600160a01b038316613aeb57604051637e27328960e01b81526004810182905260240161124e565b60405163177e802f60e01b81526001600160a01b03831660048201526024810182905260440161124e565b6001600160a01b038216613b3f57604051633250574960e11b81525f600482015260240161124e565b5f613b4b83835f61348c565b90506001600160a01b03811615610e41576040516339e3563760e11b81525f600482015260240161124e565b5f6001600160a01b038316158015906114bb5750826001600160a01b0316846001600160a01b03161480613bb05750613bb084846127d6565b806114bb5750505f908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b03198116811461118b575f5ffd5b5f60208284031215613bfd575f5ffd5b813561153781613bd8565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6115376020830184613c08565b5f60208284031215613c58575f5ffd5b5035919050565b80356001600160a01b0381168114613c75575f5ffd5b919050565b5f5f60408385031215613c8b575f5ffd5b613c9483613c5f565b946020939093013593505050565b5f60208284031215613cb2575f5ffd5b61153782613c5f565b602080825282518282018190525f918401906040840190835b81811015613cf2578351835260209384019390920191600101613cd4565b509095945050505050565b803563ffffffff81168114613c75575f5ffd5b5f5f60408385031215613d21575f5ffd5b82359150613d3160208401613cfd565b90509250929050565b80356001600160801b0381168114613c75575f5ffd5b5f5f5f5f60808587031215613d63575f5ffd5b84359350613d7360208601613cfd565b925060408501359150613d8860608601613d3a565b905092959194509250565b5f5f5f60608486031215613da5575f5ffd5b613dae84613c5f565b9250613dbc60208501613c5f565b929592945050506040919091013590565b5f60208284031215613ddd575f5ffd5b61153782613cfd565b5f5f60408385031215613df7575f5ffd5b613e0083613c5f565b915060208301358015158114613e14575f5ffd5b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613e5c57613e5c613e1f565b604052919050565b5f67ffffffffffffffff821115613e7d57613e7d613e1f565b50601f01601f191660200190565b5f5f5f5f60808587031215613e9e575f5ffd5b613ea785613c5f565b9350613eb560208601613c5f565b925060408501359150606085013567ffffffffffffffff811115613ed7575f5ffd5b8501601f81018713613ee7575f5ffd5b8035613efa613ef582613e64565b613e33565b818152886020838501011115613f0e575f5ffd5b816020840160208301375f6020838301015280935050505092959194509250565b5f5f5f60408486031215613f41575f5ffd5b833567ffffffffffffffff811115613f57575f5ffd5b8401601f81018613613f67575f5ffd5b803567ffffffffffffffff811115613f7d575f5ffd5b8660208260051b8401011115613f91575f5ffd5b6020918201979096509401359392505050565b5f5f5f5f60808587031215613fb7575f5ffd5b84359350613d7360208601613d3a565b5f5f60408385031215613fd8575f5ffd5b613fe183613d3a565b9150613d3160208401613cfd565b5f5f5f5f60808587031215614002575f5ffd5b61400b85613d3a565b9350613d7360208601613cfd565b5f5f6040838503121561402a575f5ffd5b61403383613c5f565b9150613d3160208401613c5f565b600181811c9082168061405557607f821691505b60208210810361407357634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016140b2576140b261408d565b5060010190565b63ffffffff81811683821601908111156107a1576107a161408d565b6001600160801b0382811682821603908111156107a1576107a161408d565b80820281158282048414176107a1576107a161408d565b634e487b7160e01b5f52601260045260245ffd5b5f8261412d5761412d61410b565b500490565b808201808211156107a1576107a161408d565b6001600160801b0381811683821601908111156107a1576107a161408d565b63ffffffff82811682821603908111156107a1576107a161408d565b5f63ffffffff821663ffffffff810361419b5761419b61408d565b60010192915050565b5f602082840312156141b4575f5ffd5b5051919050565b5f82518060208501845e5f920191825250919050565b5f602082840312156141e1575f5ffd5b815167ffffffffffffffff8111156141f7575f5ffd5b8201601f81018413614207575f5ffd5b8051614215613ef582613e64565b818152856020838501011115614229575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f82600f0b82600f0b0280600f0b91508082146142655761426561408d565b5092915050565b600f82810b9082900b0360016001607f1b0319811260016001607f1b03821317156107a1576107a161408d565b5f63ffffffff8316806142ae576142ae61410b565b8063ffffffff84160491505092915050565b63ffffffff81811683821602908116908181146142655761426561408d565b600f81810b9083900b0160016001607f1b03811360016001607f1b0319821217156107a1576107a161408d565b818103818111156107a1576107a161408d565b5f81600f0b83600f0b806143355761433561410b565b60016001607f1b031982145f19821416156143525761435261408d565b90059392505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f9061223a90830184613c08565b5f6020828403121561439d575f5ffd5b815161153781613bd856fea26469706673582212203b6888d2732bfd5dcfd7dcb20ed792bd78ab3c61911802ab6ecfffddb0d6307664736f6c634300081b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a000000000000000000000000854364fd5853cf618954753cd269d2d7af580c7a0000000000000000000000005e4d8755c0cbd26e8670b27bc0bd21ef84cd881d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000854657374206e66740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003544e540000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : lockedToken (address): 0x9FdfB4B79bab682E46b348C04c45123B9D4fF27a
Arg [1] : distributor (address): 0x854364Fd5853cf618954753Cd269D2d7af580C7a
Arg [2] : emergencyRecovery (address): 0x5e4D8755c0cBD26E8670b27Bc0bD21EF84cD881d
Arg [3] : name (string): Test nft
Arg [4] : symbol (string): TNT
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 0000000000000000000000009fdfb4b79bab682e46b348c04c45123b9d4ff27a
Arg [1] : 000000000000000000000000854364fd5853cf618954753cd269d2d7af580c7a
Arg [2] : 0000000000000000000000005e4d8755c0cbd26e8670b27bc0bd21ef84cd881d
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [6] : 54657374206e6674000000000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [8] : 544e540000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
145691:27276:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104713:305;;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;104713:305:0;;;;;;;;105544:91;;;:::i;:::-;;;;;;;:::i;106716:158::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1506:32:1;;;1488:51;;1476:2;1461:18;106716:158:0;1342:203:1;106535:115:0;;;;;;:::i;:::-;;:::i;:::-;;171099:562;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;147737:68::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;147737:68:0;;;;;;;;;;-1:-1:-1;;;147737:68:0;;;;;;;;;3563:2:1;3552:22;;;3534:41;;3611:22;;;;3606:2;3591:18;;3584:50;3682:10;3670:23;;;3650:18;;;3643:51;;;;3730:23;;;3725:2;3710:18;;3703:51;3521:3;3506:19;147737:68:0;3311:449:1;160253:2509:0;;;;;;:::i;:::-;;:::i;170724:96::-;170798:14;;-1:-1:-1;;;170798:14:0;;;;170724:96;;155390:191;;;;;;:::i;:::-;;:::i;170828:109::-;170909:20;;-1:-1:-1;;;;;170909:20:0;170828:109;;;-1:-1:-1;;;;;4999:47:1;;;4981:66;;4969:2;4954:18;170828:109:0;4835:218:1;155827:1495:0;;;;;;:::i;:::-;;:::i;170945:146::-;;;;;;:::i;:::-;;:::i;108044:134::-;;;;;;:::i;:::-;;:::i;169907:586::-;;;;;;:::i;:::-;;:::i;147864:23::-;;;;;-1:-1:-1;;;;;147864:23:0;;;147812:45;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;5420:2:1;5409:22;;;;5391:41;;5379:2;5364:18;147812:45:0;5247:191:1;141154:86:0;141225:7;;;;141154:86;;105357:120;;;;;;:::i;:::-;;:::i;105082:213::-;;;;;;:::i;:::-;;:::i;:::-;;;5589:25:1;;;5577:2;5562:18;105082:213:0;5443:177:1;144356:103:0;;;:::i;147463:46::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;147463:46:0;;;;-1:-1:-1;;;147463:46:0;;;;;;;;;-1:-1:-1;;;147463:46:0;;;;;;;;;-1:-1:-1;;;;;5870:47:1;;;5852:66;;5954:47;;;;5949:2;5934:18;;5927:75;6050:10;6038:23;;;6018:18;;;6011:51;;;;6098:23;6093:2;6078:18;;6071:51;5839:3;5824:19;147463:46:0;5625:503:1;150084:425:0;;;;;;:::i;:::-;;:::i;143681:87::-;143754:6;;;;;-1:-1:-1;;;;;143754:6:0;143681:87;;147605:44;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;147605:44:0;;;;;;;;;;-1:-1:-1;;;147605:44:0;;;;;147656:19;;;;;;;;;;;;6307:10:1;6295:23;;;6277:42;;6265:2;6250:18;147656:19:0;6133:192:1;105704:95:0;;;:::i;164672:199::-;;;;;;:::i;:::-;;:::i;170600:116::-;;;;;;:::i;:::-;-1:-1:-1;;;;;170688:20:0;170663:5;170688:20;;;:14;:20;;;;;;;;;170600:116;;;;6502:4:1;6490:17;;;6472:36;;6460:2;6445:18;170600:116:0;6330:184:1;106946:146:0;;;;;;:::i;:::-;;:::i;155589:226::-;;;;;;:::i;:::-;;:::i;166135:2544::-;;;;;;:::i;:::-;;:::i;147517:47::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;162768:1896;;;;;;:::i;:::-;;:::i;169727:172::-;;;:::i;171665:495::-;;;;;;:::i;:::-;;:::i;172164:800::-;;;;;;:::i;:::-;;:::i;168687:490::-;;;;;;:::i;:::-;;:::i;169185:506::-;;;;;;:::i;:::-;;:::i;158451:1794::-;;;;;;:::i;:::-;;:::i;147682:48::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;107163:155;;;;;;:::i;:::-;;:::i;144614:220::-;;;;;;:::i;:::-;;:::i;170501:68::-;;;:::i;104713:305::-;104815:4;-1:-1:-1;;;;;;104852:40:0;;-1:-1:-1;;;104852:40:0;;:105;;-1:-1:-1;;;;;;;104909:48:0;;-1:-1:-1;;;104909:48:0;104852:105;:158;;;-1:-1:-1;;;;;;;;;;103546:40:0;;;104974:36;104832:178;104713:305;-1:-1:-1;;104713:305:0:o;105544:91::-;105589:13;105622:5;105615:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105544:91;:::o;106716:158::-;106783:7;106803:22;106817:7;106803:13;:22::i;:::-;-1:-1:-1;109318:7:0;109345:24;;;:15;:24;;;;;;-1:-1:-1;;;;;109345:24:0;106845:21;109248:129;106535:115;106607:35;106616:2;106620:7;16239:10;106607:8;:35::i;:::-;106535:115;;:::o;171099:562::-;-1:-1:-1;;;;;171212:21:0;;171198:11;171212:21;;;:14;:21;;;;;;171160:25;;171212:21;;;171255:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;171255:20:0;;171244:31;;171290:5;:10;;171299:1;171290:10;171286:31;;171302:15;171099:562;;;:::o;171286:31::-;171338:20;;171373:245;171399:12;;-1:-1:-1;;;171399:12:0;;;;171394:17;;171373:245;;;109076:7;109103:16;;;:7;:16;;;;;;-1:-1:-1;;;;;171438:21:0;;;109103:16;;171438:21;171434:173;;171505:2;171480:8;171489:12;171480:22;;;;;;;;:::i;:::-;;;;;;;;;;:27;171526:14;;;;:::i;:::-;;;;171579:5;171563:21;;:12;:21;171559:32;171586:5;171559:32;;171413:4;;171373:245;;;;171638:15;;171099:562;;;:::o;160253:2509::-;138717:21;:19;:21::i;:::-;140759:19:::1;:17;:19::i;:::-;160444:8:::2;149852;149834:15;:26;149830:56;;;149869:17;;-1:-1:-1::0;;;149869:17:0::2;;;;;;;;;;;149830:56;160517:10:::3;160497:16;160505:7:::0;160497::::3;:16::i;:::-;-1:-1:-1::0;;;;;160497:30:0::3;;160493:58;;160536:15;;-1:-1:-1::0;;;160536:15:0::3;;;;;;;;;;;160493:58;160601:24;160628:15:::0;;;:6:::3;:15;::::0;;;;;;;160601:42;;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;;;160601:42:0;;::::3;::::0;;;-1:-1:-1;;;160601:42:0;;::::3;;::::0;;::::3;::::0;;;;;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;;;;;-1:-1:-1;;;160601:42:0;::::3;::::0;;::::3;::::0;;;;;160658:16;160654:44:::3;;160683:15;;-1:-1:-1::0;;;160683:15:0::3;;;;;;;;;;;160654:44;160787:4;:12;;;160760:39;;160767:15;160760:39;;;160756:68;;160808:16;;-1:-1:-1::0;;;160808:16:0::3;;;;;;;;;;;160756:68;160880:17;160900:37;160926:11:::0;160907:15:::3;160900:37;:::i;:::-;160880:57:::0;-1:-1:-1;160952:16:0::3;::::0;::::3;::::0;;:66:::3;;-1:-1:-1::0;160985:33:0::3;146894:8;160992:15;160985:33;:::i;:::-;160972:46;;:10;:46;;;160952:66;160948:110;;;161041:17;;-1:-1:-1::0;;;161041:17:0::3;;;;;;;;;;;160948:110;161111:17;146894:8;161156:32;147052:4;146998;161156:32;:::i;:::-;161140:11:::0;;161132:57:::3;::::0;-1:-1:-1;;;;;161132:57:0;;::::3;::::0;:20:::3;:57;:::i;:::-;161131:69;;;;:::i;:::-;161111:89:::0;-1:-1:-1;;;;;;161215:29:0;::::3;161211:57;;;161253:15;;-1:-1:-1::0;;;161253:15:0::3;;;;;;;;;;;161211:57;161306:9:::0;161279:16:::3;161449:31;;::::0;::::3;-1:-1:-1::0;;;;;161449:17:0;::::3;:31;:::i;:::-;161430:51;::::0;147052:4:::3;161430:51;:::i;:::-;161401:81;;161510:13;-1:-1:-1::0;;;;;161497:26:0::3;:10;-1:-1:-1::0;;;;;161497:26:0::3;;161493:57;;;161532:18;;-1:-1:-1::0;;;161532:18:0::3;;;;;;;;;;;161493:57;146998:4;-1:-1:-1::0;;;;;161565:27:0;::::3;;161561:59;;;161601:19;;-1:-1:-1::0;;;161601:19:0::3;;;;;;;;;;;161561:59;161701:30;161734:109;;;;;;;;161786:4;:11;;;161734:109;;;;;;161819:4;:12;;;161734:109;;;;::::0;161701:142:::3;;161864:30;161897:107;;;;;;;;161949:4;:11;;;161897:107;;;;;;161982:10;161897:107;;;;::::0;161864:140:::3;;162068:173;;;;;;;;162104:4;:11;;;-1:-1:-1::0;;;;;162068:173:0::3;;;;;162221:8;-1:-1:-1::0;;;;;162068:173:0::3;;;;;162139:10;162068:173;;;;;;162183:15;162068:173;;;;::::0;162050:6:::3;:15;162057:7;162050:15;;;;;;;;;;;:191;;;;;;;;;;;;;-1:-1:-1::0;;;;;162050:191:0::3;;;;;-1:-1:-1::0;;;;;162050:191:0::3;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;162050:191:0::3;;;;;-1:-1:-1::0;;;;;162050:191:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;162297:25;147100:4;-1:-1:-1::0;;;;;162325:66:0::3;162349:29;162370:7;162349:20;:29::i;:::-;162334:11:::0;;162326:52:::3;::::0;-1:-1:-1;;;;;162326:52:0;;::::3;::::0;:20:::3;:52;:::i;:::-;162325:66;;;;:::i;:::-;162439:11:::0;;162297:94;;-1:-1:-1;162402:25:0::3;::::0;147100:4:::3;::::0;162431:33:::3;::::0;-1:-1:-1;;;;;162431:33:0;;::::3;::::0;:20:::3;:33;:::i;:::-;162430:47;;;;:::i;:::-;162511:20;::::0;162402:75;;-1:-1:-1;162402:75:0;;162511:49:::3;::::0;162542:17;;-1:-1:-1;;;;;162511:20:0::3;:49;:::i;:::-;:78;;;;:::i;:::-;162488:20;:101:::0;;-1:-1:-1;;;;;;162488:101:0::3;-1:-1:-1::0;;;;;162488:101:0;;;::::3;::::0;;;::::3;::::0;;162633:42:::3;162645:7:::0;162654:9;162665;162633:11:::3;:42::i;:::-;162701:57;::::0;;12868:10:1;12856:23;;12838:42;;-1:-1:-1;;;;;12916:47:1;;12911:2;12896:18;;12889:75;162726:7:0;;162714:10:::3;::::0;162701:57:::3;::::0;12811:18:1;162701:57:0::3;;;;;;;160454:2308;;;;;;;;;140789:1:::2;138761:20:::0;138155:1;139281:7;:22;139098:213;138761:20;160253:2509;;;;:::o;155390:191::-;155490:35;155511:4;155517:7;155490:20;:35::i;:::-;155536:36;155555:4;155560:2;155564:7;155536:18;:36::i;:::-;155390:191;;;:::o;155827:1495::-;138717:21;:19;:21::i;:::-;155895:13:::1;109103:16:::0;;;:7;:16;;;;;;-1:-1:-1;;;;;109103:16:0;;155939:48:::1;;155971:16;;-1:-1:-1::0;;;155971:16:0::1;;;;;;;;;;;155939:48;-1:-1:-1::0;;;;;156002:19:0;::::1;156011:10;156002:19;155998:47;;156030:15;;-1:-1:-1::0;;;156030:15:0::1;;;;;;;;;;;155998:47;156066:24;156093:15:::0;;;:6:::1;:15;::::0;;;;;;;156066:42;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;156066:42:0;;::::1;::::0;;;-1:-1:-1;;;156066:42:0;;::::1;;::::0;;::::1;::::0;;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;156066:42:0;::::1;::::0;;::::1;::::0;;;;;156123:16;156119:44:::1;;156148:15;;-1:-1:-1::0;;;156148:15:0::1;;;;;;;;;;;156119:44;156204:4;:12;;;156178:38;;156185:15;156178:38;;;156174:67;;;156225:16;;-1:-1:-1::0;;;156225:16:0::1;;;;;;;;;;;156174:67;156279:11:::0;;156342:104:::1;::::0;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;156422:12;;::::1;::::0;156342:104:::1;;;::::0;;::::1;::::0;;;;156262:14:::1;156466:15:::0;;;:6:::1;:15:::0;;;;;;156459:22;;;;::::1;::::0;;-1:-1:-1;;156459:22:0;;;156342:104;156523:29:::1;156473:7:::0;156523:20:::1;:29::i;:::-;156502:50:::0;-1:-1:-1;156563:22:0::1;147100:4;156589:37;-1:-1:-1::0;;;;;156607:19:0;;::::1;::::0;156589:15;::::1;:37;:::i;:::-;156588:51;;;;:::i;:::-;156563:76;;156698:10;-1:-1:-1::0;;;;;156690:19:0::1;156679:6;-1:-1:-1::0;;;;;156671:15:0::1;156654:14;:32;;;;:::i;:::-;:55;156650:85;;156718:17;;-1:-1:-1::0;;;156718:17:0::1;;;;;;;;;;;156650:85;156746:30;156779:26;147100:4;156779:14:::0;:26:::1;:::i;:::-;156746:59:::0;-1:-1:-1;;;;;;156820:42:0;::::1;156816:70;;;156871:15;;-1:-1:-1::0;;;156871:15:0::1;;;;;;;;;;;156816:70;156897:20;:55:::0;;156929:22;;156897:20;::::1;::::0;:55:::1;::::0;156929:22;;-1:-1:-1;;;;;156897:55:0::1;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;156897:55:0::1;;;;;-1:-1:-1::0;;;;;156897:55:0::1;;;;;;156973:50;156985:7;156994;157003:19;;;;;;;;157017:1;157003:19;;;;;;157020:1;157003:19;;;;::::0;156973:11:::1;:50::i;:::-;157051:23;::::0;;;:14:::1;:23;::::0;;;;157044:30;;-1:-1:-1;;157044:30:0::1;::::0;;157095:14:::1;157066:7:::0;157095:5:::1;:14::i;:::-;157160:10;157145:26;::::0;;;:14:::1;:26;::::0;;;;:28;;-1:-1:-1;;157145:28:0;::::1;;::::0;;::::1;-1:-1:-1::0;;157145:28:0;;;::::1;;::::0;;157205:46:::1;::::0;-1:-1:-1;;;;;157205:13:0::1;:26;::::0;-1:-1:-1;;;;;157205:46:0;::::1;:26;:46::i;:::-;157277:37;::::0;-1:-1:-1;;;;;4999:47:1;;4981:66;;157298:7:0;;157286:10:::1;::::0;157277:37:::1;::::0;4969:2:1;4954:18;157277:37:0::1;;;;;;;155884:1438;;;;;;;138761:20:::0;138155:1;139281:7;:22;139098:213;138761:20;155827:1495;:::o;170945:146::-;143567:13;:11;:13::i;:::-;-1:-1:-1;;;;;171015:23:0;::::1;171011:49;;171047:13;;-1:-1:-1::0;;;171047:13:0::1;;;;;;;;;;;171011:49;171067:8;:20:::0;;-1:-1:-1;;;;;;171067:20:0::1;-1:-1:-1::0;;;;;171067:20:0;;;::::1;::::0;;;::::1;::::0;;170945:146::o;108044:134::-;108131:39;108148:4;108154:2;108158:7;108131:39;;;;;;;;;;;;:16;:39::i;169907:586::-;138717:21;:19;:21::i;:::-;169992:14:::1;::::0;-1:-1:-1;;;169992:14:0;::::1;;;169984:48;;;::::0;-1:-1:-1;;;169984:48:0;;13177:2:1;169984:48:0::1;::::0;::::1;13159:21:1::0;13216:2;13196:18;;;13189:30;-1:-1:-1;;;13235:18:1;;;13228:51;13296:18;;169984:48:0::1;;;;;;;;;170067:10;170047:16;170055:7:::0;170047::::1;:16::i;:::-;-1:-1:-1::0;;;;;170047:30:0::1;;170043:58;;170086:15;;-1:-1:-1::0;;;170086:15:0::1;;;;;;;;;;;170043:58;170122:24;170149:15:::0;;;:6:::1;:15;::::0;;;;;;;170122:42;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;170122:42:0;;::::1;::::0;;;-1:-1:-1;;;170122:42:0;;::::1;;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;170122:42:0;::::1;::::0;;::::1;::::0;;;;170231:15;;;;;;;170224:22;;;-1:-1:-1;;170224:22:0;;;;170257:14:::1;170156:7:::0;170257:5:::1;:14::i;:::-;170322:10;170307:26;::::0;;;:14:::1;:26;::::0;;;;:28;;-1:-1:-1;;170307:28:0;::::1;;::::0;;::::1;-1:-1:-1::0;;170307:28:0;;;::::1;;::::0;;170367:46:::1;::::0;-1:-1:-1;;;;;170367:13:0::1;:26;::::0;-1:-1:-1;;;;;170367:46:0;::::1;:26;:46::i;:::-;170439;::::0;-1:-1:-1;;;;;4999:47:1;;4981:66;;170469:7:0;;170457:10:::1;::::0;170439:46:::1;::::0;4969:2:1;4954:18;170439:46:0::1;;;;;;;169973:520;;138761:20:::0;138155:1;139281:7;:22;139098:213;105357:120;105420:7;105447:22;105461:7;105447:13;:22::i;105082:213::-;105145:7;-1:-1:-1;;;;;105169:19:0;;105165:89;;105212:30;;-1:-1:-1;;;105212:30:0;;105239:1;105212:30;;;1488:51:1;1461:18;;105212:30:0;1342:203:1;105165:89:0;-1:-1:-1;;;;;;105271:16:0;;;;;:9;:16;;;;;;;105082:213::o;144356:103::-;143567:13;:11;:13::i;:::-;144421:30:::1;144448:1;144421:18;:30::i;:::-;144356:103::o:0;150084:425::-;150152:7;150199:15;;;:6;:15;;;;;;;;150172:42;;;;;;;;;-1:-1:-1;;;;;150172:42:0;;;;;-1:-1:-1;;;150172:42:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;150172:42:0;;;;;;;;;150236:15;150229:39;;150225:67;;-1:-1:-1;147052:4:0;;150084:425;-1:-1:-1;;150084:425:0:o;150225:67::-;150313:15;150397;150375:4;:12;;;:38;150364:49;;150491:8;150469:30;;150477:4;:10;;;-1:-1:-1;;;;;150469:19:0;:30;;;;:::i;:::-;150450:50;;147052:4;150450:50;:::i;:::-;150435:66;150084:425;-1:-1:-1;;;;150084:425:0:o;105704:95::-;105751:13;105784:7;105777:14;;;;;:::i;164672:199::-;164799:5;;;;;;164741:7;164786:19;;;:12;:19;;;;;;;;164761:44;;;;;;;;;;;;;;;-1:-1:-1;;;164761:44:0;;;;;;;;;;;;164799:5;164761:44;;;;;;;;;;;;-1:-1:-1;;;164761:44:0;;;;;;;;;164741:7;164831:31;164761:44;164852:9;164831;:31::i;:::-;164816:47;164672:199;-1:-1:-1;;;164672:199:0:o;106946:146::-;107032:52;16239:10;107065:8;107075;107032:18;:52::i;155589:226::-;155713:35;155734:4;155740:7;155713:20;:35::i;:::-;155760:47;155783:4;155789:2;155793:7;155802:4;155760:22;:47::i;166135:2544::-;138717:21;:19;:21::i;:::-;140759:19:::1;:17;:19::i;:::-;166272:8:::2;149852;149834:15;:26;149830:56;;;149869:17;;-1:-1:-1::0;;;149869:17:0::2;;;;;;;;;;;149830:56;166315:1:::3;166297:19:::0;::::3;166293:47;;;166325:15;;-1:-1:-1::0;;;166325:15:0::3;;;;;;;;;;;166293:47;166361:19;::::0;;166496:376:::3;166516:19:::0;;::::3;166496:376;;;166585:10;166561:20;166569:8:::0;;166578:1;166569:11;;::::3;;;;;:::i;:::-;;;;;;;166561:7;:20::i;:::-;-1:-1:-1::0;;;;;166561:34:0::3;;166557:62;;166604:15;;-1:-1:-1::0;;;166604:15:0::3;;;;;;;;;;;166557:62;166648:24;166675:6;:19;166682:8;;166691:1;166682:11;;;;;;;:::i;:::-;;::::0;;::::3;::::0;;;::::3;;166675:19:::0;;-1:-1:-1;166675:19:0;;::::3;::::0;;;;;;;;-1:-1:-1;166675:19:0;166648:46;;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;;;166648:46:0;;::::3;::::0;;;-1:-1:-1;;;166648:46:0;;::::3;;::::0;;::::3;::::0;;;;;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;;;;;-1:-1:-1;;;166648:46:0;::::3;::::0;;::::3;::::0;;;;;-1:-1:-1;166723:26:0::3;::::0;;::::3;:::i;:::-;;;166783:13;166768:28;;:4;:12;;;:28;;;166764:97;;;166833:4;:12;;;166817:28;;166764:97;-1:-1:-1::0;166537:3:0::3;;166496:376;;;-1:-1:-1::0;166931:24:0::3;166958:39;166981:15;166958:13:::0;:39:::3;:::i;:::-;166931:66:::0;-1:-1:-1;146894:8:0::3;167012:27;::::0;::::3;;167008:57;;;167048:17;;-1:-1:-1::0;;;167048:17:0::3;;;;;;;;;;;167008:57;167086:17;146894:8;167131:32;147052:4;146998;167131:32;:::i;:::-;-1:-1:-1::0;;;;;167107:57:0::3;167115:11;-1:-1:-1::0;;;;;167107:20:0::3;:57;;;;:::i;:::-;167106:69;;;;:::i;:::-;167086:89:::0;-1:-1:-1;;;;;;167190:29:0;::::3;167186:57;;;167228:15;;-1:-1:-1::0;;;167228:15:0::3;;;;;;;;;;;167186:57;167335:12;167333:14:::0;;167281:9;;167254:16:::3;::::0;167335:12:::3;::::0;167333:14:::3;::::0;-1:-1:-1;;;167333:14:0;::::3;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;167312:35;;;;167358:33;167368:10;167380;167358:9;:33::i;:::-;167466:9;167461:512;167481:19:::0;;::::3;167461:512;;;167522:15;167540:8;;167549:1;167540:11;;;;;;;:::i;:::-;;::::0;;::::3;::::0;;;::::3;;167566:27;167596:15:::0;;;:6:::3;:15:::0;;;;;;167566:45;;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;;;167566:45:0;;::::3;::::0;;-1:-1:-1;;;167566:45:0;;::::3;;::::0;;::::3;::::0;;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;;;;-1:-1:-1;;;167566:45:0;;::::3;::::0;::::3;::::0;;;;167680:127;;;;::::3;::::0;;167736:14;;167680:127:::3;;::::0;;167776:15;;167680:127:::3;::::0;;::::3;::::0;167875:19;;;;::::3;::::0;;;;;;;;::::3;::::0;;;;167540:11;;-1:-1:-1;167566:45:0;167680:127;-1:-1:-1;167836:59:0::3;::::0;167540:11;;167680:127;;167836:11:::3;:59::i;:::-;167917:15;::::0;;;:6:::3;:15;::::0;;;;167910:22;;;;::::3;::::0;;-1:-1:-1;;167910:22:0;;;167947:14:::3;167924:7:::0;167947:5:::3;:14::i;:::-;-1:-1:-1::0;;;167502:3:0::3;;167461:512;;;-1:-1:-1::0;168044:110:0::3;::::0;;;;::::3;::::0;;::::3;::::0;;::::3;::::0;;::::3;::::0;::::3;;::::0;;::::3;::::0;;;;168199:19;;;;::::3;::::0;;;168013:28:::3;168199:19:::0;;;;;::::3;::::0;168044:110;168175:53:::3;::::0;168187:10;;168044:110;168175:11:::3;:53::i;:::-;168270:176;;;;;;;;168306:11;-1:-1:-1::0;;;;;168270:176:0::3;;;;;168426:8;-1:-1:-1::0;;;;;168270:176:0::3;;;;;168341:13;168270:176;;;;;;168388:15;168270:176;;;;::::0;168249:6:::3;:18;168256:10;168249:18;;;;;;;;;;;:197;;;;;;;;;;;;;-1:-1:-1::0;;;;;168249:197:0::3;;;;;-1:-1:-1::0;;;;;168249:197:0::3;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;168249:197:0::3;;;;;-1:-1:-1::0;;;;;168249:197:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;168554:8;;:15;;168519:14;:26;168534:10;-1:-1:-1::0;;;;;168519:26:0::3;-1:-1:-1::0;;;;;168519:26:0::3;;;;;;;;;;;;;;;;;;;;;;:51;168573:1;168519:55;168484:14;:26;168499:10;-1:-1:-1::0;;;;;168484:26:0::3;-1:-1:-1::0;;;;;168484:26:0::3;;;;;;;;;;;;;:91;;;;;;;;;;;;;;;;;;168632:10;168620;-1:-1:-1::0;;;;;168612:59:0::3;;168644:11;168657:13;168612:59;;;;;;-1:-1:-1::0;;;;;13883:47:1;;;;13865:66;;13979:10;13967:23;13962:2;13947:18;;13940:51;13853:2;13838:18;;13693:304;168612:59:0::3;;;;;;;;166282:2397;;;;;;;140789:1:::2;138761:20:::0;138155:1;139281:7;:22;139098:213;162768:1896;138717:21;:19;:21::i;:::-;140759:19:::1;:17;:19::i;:::-;162953:8:::2;149852;149834:15;:26;149830:56;;;149869:17;;-1:-1:-1::0;;;149869:17:0::2;;;;;;;;;;;149830:56;162994:10:::3;162974:16;162982:7:::0;162974::::3;:16::i;:::-;-1:-1:-1::0;;;;;162974:30:0::3;;162970:58;;163013:15;;-1:-1:-1::0;;;163013:15:0::3;;;;;;;;;;;162970:58;163039:16;-1:-1:-1::0;;;;;163039:21:0::3;163059:1;163039:21:::0;163035:49:::3;;163069:15;;-1:-1:-1::0;;;163069:15:0::3;;;;;;;;;;;163035:49;163097:24;163124:15:::0;;;:6:::3;:15;::::0;;;;;;;163097:42;;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;;;163097:42:0;;::::3;::::0;;;-1:-1:-1;;;163097:42:0;;::::3;;::::0;;::::3;::::0;;;;;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;;;;;-1:-1:-1;;;163097:42:0;::::3;::::0;;::::3;::::0;;;;;163150:16;163146:44:::3;;163175:15;;-1:-1:-1::0;;;163175:15:0::3;;;;;;;;;;;163146:44;163228:4;:12;;;163201:39;;163208:15;163201:39;;;163197:68;;163249:16;;-1:-1:-1::0;;;163249:16:0::3;;;;;;;;;;;163197:68;163278:24;163327:15;163305:4;:12;;;:38;;;;:::i;:::-;163278:65;;163350:17;163384:16;163370:4;:11;;;:30;;;;:::i;:::-;163350:50;;163470:18;163491:51;163513:9;163524:17;163491:21;:51::i;:::-;163470:72;;163566:13;-1:-1:-1::0;;;;;163553:26:0::3;:10;-1:-1:-1::0;;;;;163553:26:0::3;;163549:57;;;163588:18;;-1:-1:-1::0;;;163588:18:0::3;;;;;;;;;;;163549:57;163673:38;::::0;-1:-1:-1;;;163673:38:0;;163705:4:::3;163673:38;::::0;::::3;1488:51:1::0;163649:21:0::3;::::0;163673:13:::3;-1:-1:-1::0;;;;;163673:23:0::3;::::0;::::3;::::0;1461:18:1;;163673:38:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;163649:62:::0;-1:-1:-1;163718:75:0::3;-1:-1:-1::0;;;;;163718:13:0::3;:30;163749:10;163769:4;-1:-1:-1::0;;;;;163718:75:0;::::3;:30;:75::i;:::-;163846:32;-1:-1:-1::0;;;;;163846:32:0;::::3;:13:::0;:32:::3;:::i;:::-;163804:38;::::0;-1:-1:-1;;;163804:38:0;;163836:4:::3;163804:38;::::0;::::3;1488:51:1::0;163804:13:0::3;-1:-1:-1::0;;;;;163804:23:0::3;::::0;::::3;::::0;1461:18:1;;163804:38:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:74;163800:112;;163896:16;;-1:-1:-1::0;;;163896:16:0::3;;;;;;;;;;;163800:112;163992:97;::::0;;;;::::3;::::0;;164040:11;;163992:97:::3;::::0;;::::3;::::0;;164069:12;;::::3;::::0;;163992:97:::3;::::0;;::::3;;::::0;;::::3;::::0;;;;164135:95;;;;::::3;::::0;;;;;::::3;::::0;;164210:12;;164135:95:::3;::::0;;::::3;::::0;-1:-1:-1;164264:15:0;;;:6:::3;:15:::0;;;;;;;:34;;-1:-1:-1;;;;;;164264:34:0::3;-1:-1:-1::0;;;;;164264:34:0;::::3;;::::0;;163992:97;146894:8:::3;164360:32;147052:4;146998;164360:32;:::i;:::-;-1:-1:-1::0;;;;;164338:55:0::3;164346:9;-1:-1:-1::0;;;;;164338:18:0::3;:55;;;;:::i;:::-;164337:67;;;;:::i;:::-;164305:15;::::0;;;:6:::3;:15;::::0;;;;:100;;-1:-1:-1;;;;;164305:100:0;;::::3;-1:-1:-1::0;;;164305:100:0::3;::::0;::::3;::::0;;;::::3;::::0;;-1:-1:-1;164412:26:0::3;:52:::0;;::::3;164448:15;164412:52;-1:-1:-1::0;;;164412:52:0::3;-1:-1:-1::0;;164412:52:0;;::::3;;::::0;;164523:42:::3;164312:7:::0;164544:9;164555;164523:11:::3;:42::i;:::-;164583:77;::::0;;-1:-1:-1;;;;;14411:47:1;;;14393:66;;14495:47;;;14490:2;14475:18;;14468:75;14579:47;;14559:18;;;14552:75;164583:77:0;;164611:7;;164599:10:::3;::::0;164583:77:::3;::::0;;;;14381:2:1;164583:77:0;;::::3;162963:1701;;;;;;;140789:1:::2;138761:20:::0;138155:1;139281:7;:22;139098:213;169727:172;143567:13;:11;:13::i;:::-;169788:14:::1;:21:::0;;-1:-1:-1;;;;169788:21:0::1;-1:-1:-1::0;;;169788:21:0::1;::::0;;169820:8:::1;:6;:8::i;:::-;169865:25;::::0;169844:47:::1;::::0;-1:-1:-1;;;;;169865:25:0;;::::1;1488:51:1::0;;169844:47:0::1;::::0;1476:2:1;1461:18;169844:47:0::1;;;;;;;;169727:172::o:0;171665:495::-;171793:1;109103:16;;;:7;:16;;;;;;171738:13;;-1:-1:-1;;;;;109103:16:0;171760:60;;171804:16;;-1:-1:-1;;;171804:16:0;;;;;;;;;;;171760:60;171831:8;;-1:-1:-1;;;;;171831:8:0;171827:52;;171862:17;;-1:-1:-1;;;171862:17:0;;;;;;;;;;;171827:52;171972:8;;172002:53;;;;;5589:25:1;;;171937:12:0;;;;-1:-1:-1;;;;;171972:8:0;;;;5562:18:1;;172002:53:0;;;-1:-1:-1;;172002:53:0;;;;;;;;;;;;;;-1:-1:-1;;;;;172002:53:0;-1:-1:-1;;;172002:53:0;;;171972:90;;;172002:53;171972:90;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;171936:126;;;;172077:7;172069:41;;;;-1:-1:-1;;;172069:41:0;;15146:2:1;172069:41:0;;;15128:21:1;15185:2;15165:18;;;15158:30;-1:-1:-1;;;15204:18:1;;;15197:51;15265:18;;172069:41:0;14944:345:1;172069:41:0;172141:4;172130:26;;;;;;;;;;;;:::i;172164:800::-;172249:7;172269:13;;;;;:35;;-1:-1:-1;146894:8:0;172286:18;;;;172269:35;172265:65;;;172313:17;;-1:-1:-1;;;172313:17:0;;;;;;;;;;;172265:65;172341:6;-1:-1:-1;;;;;172341:11:0;172351:1;172341:11;172337:39;;172361:15;;-1:-1:-1;;;172361:15:0;;;;;;;;;;;172337:39;172413:17;146894:8;172453:32;147052:4;146998;172453:32;:::i;:::-;-1:-1:-1;;;;;172434:52:0;172442:6;-1:-1:-1;;;;;172434:15:0;:52;;;;:::i;:::-;172433:64;;;;:::i;:::-;172413:84;-1:-1:-1;;;;;;172508:29:0;;172504:57;;;172546:15;;-1:-1:-1;;;172546:15:0;;;;;;;;;;;172504:57;172592:9;172568:13;172673:25;;;;-1:-1:-1;;;;;172673:14:0;;:25;:::i;:::-;172644:54;-1:-1:-1;172705:23:0;172731:36;172644:54;147052:4;172731:36;:::i;:::-;172705:62;-1:-1:-1;146998:4:0;172784:32;;172780:64;;;172825:19;;-1:-1:-1;;;172825:19:0;;;;;;;;;;;172780:64;147052:4;172855:33;;172851:65;;;172897:19;;-1:-1:-1;;;172897:19:0;;;;;;;;;;;172851:65;172944:15;172164:800;-1:-1:-1;;;;;;172164:800:0:o;168687:490::-;168768:7;168807:23;;;:14;:23;;;;;;;;168845:14;;;168841:28;;168868:1;168861:8;;;;;168841:28;168882:22;168907:25;;;:16;:25;;;;;;;;:36;;;;;;;;;;;;;168882:61;;;;;;;;;;;;;;;-1:-1:-1;;;168882:61:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;168882:61:0;;;;;;;;;;169005:24;;:9;:24;:::i;:::-;168997:33;;168972:9;:15;;;:59;;;;:::i;:::-;168954:77;;:9;;:77;;;;;:::i;:::-;;;;;;;;169046:14;;169063:1;169046:18;;;169042:69;;-1:-1:-1;169042:69:0;;169098:1;169081:18;;169042:69;169152:14;-1:-1:-1;;;;;169136:32:0;;168687:490;-1:-1:-1;;;;168687:490:0:o;169185:506::-;169364:15;;169269:7;;;;169364:15;-1:-1:-1;;;169364:15:0;;;;;169349:30;;;;:78;;169415:12;169349:78;;;169397:15;;169382:30;;-1:-1:-1;;;169397:15:0;;;;169382:12;:30;:::i;:::-;169328:99;-1:-1:-1;169491:17:0;146894:8;169531:32;147052:4;146998;169531:32;:::i;:::-;-1:-1:-1;;;;;169512:52:0;169520:6;-1:-1:-1;;;;;169512:15:0;:52;;;;:::i;:::-;169511:64;;;;:::i;:::-;169491:84;-1:-1:-1;169491:84:0;169657:28;;;;-1:-1:-1;;;;;169657:14:0;;:28;:::i;:::-;169638:48;;147052:4;169638:48;:::i;158451:1794::-;158661:15;138717:21;:19;:21::i;:::-;140759:19:::1;:17;:19::i;:::-;158642:8:::2;149852;149834:15;:26;149830:56;;;149869:17;;-1:-1:-1::0;;;149869:17:0::2;;;;;;;;;;;149830:56;158693:6:::3;-1:-1:-1::0;;;;;158693:11:0::3;158703:1;158693:11:::0;158689:39:::3;;158713:15;;-1:-1:-1::0;;;158713:15:0::3;;;;;;;;;;;158689:39;158743:17;::::0;::::3;::::0;;:43:::3;;-1:-1:-1::0;146894:8:0::3;158764:22;::::0;::::3;;158743:43;158739:73;;;158795:17;;-1:-1:-1::0;;;158795:17:0::3;;;;;;;;;;;158739:73;158842:10;158827:26;::::0;;;:14:::3;:26;::::0;;;;;147155:3:::3;158827:48;:26:::0;;::::3;:48;158823:78;;158884:17;;-1:-1:-1::0;;;158884:17:0::3;;;;;;;;;;;158823:78;158922:17;158942:38;158968:12:::0;158949:15:::3;158942:38;:::i;:::-;158922:58;;159002:13;159017:18;159039:61;159064:6;159072:12;159086:13;159039:24;:61::i;:::-;159001:99;;;;159157:28;159188:102;;;;;;;;159240:6;159188:102;;;;;;159268:10;159188:102;;;;::::0;159157:133:::3;;159357:44;159369:1;159372:19;;;;;;;;159386:1;159372:19;;;;;;159389:1;159372:19;;;;::::0;159393:7:::3;159357:11;:44::i;:::-;159490:38;::::0;-1:-1:-1;;;159490:38:0;;159522:4:::3;159490:38;::::0;::::3;1488:51:1::0;159466:21:0::3;::::0;159490:13:::3;-1:-1:-1::0;;;;;159490:23:0::3;::::0;::::3;::::0;1461:18:1;;159490:38:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;159466:62:::0;-1:-1:-1;159539:65:0::3;-1:-1:-1::0;;;;;159539:13:0::3;:30;159570:10;159590:4;-1:-1:-1::0;;;;;159539:65:0;::::3;:30;:65::i;:::-;159661:22;-1:-1:-1::0;;;;;159661:22:0;::::3;:13:::0;:22:::3;:::i;:::-;159619:38;::::0;-1:-1:-1;;;159619:38:0;;159651:4:::3;159619:38;::::0;::::3;1488:51:1::0;159619:13:0::3;-1:-1:-1::0;;;;;159619:23:0::3;::::0;::::3;::::0;1461:18:1;;159619:38:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:64;159615:107;;159706:16;;-1:-1:-1::0;;;159706:16:0::3;;;;;;;;;;;159615:107;159778:12;:14:::0;;::::3;;-1:-1:-1::0;;;159778:14:0;;::::3;::::0;::::3;::::0;;::::3;::::0;;::::3;;-1:-1:-1::0;;;;159778:14:0;;::::3;::::0;;;::::3;::::0;;;159822:10:::3;-1:-1:-1::0;159807:26:0;;;:14:::3;:26;::::0;;;;:28;;::::3;::::0;;::::3;::::0;;::::3;::::0;;::::3;-1:-1:-1::0;;159807:28:0;;::::3;::::0;;;::::3;::::0;;;159778:14;-1:-1:-1;159867:30:0::3;::::0;159778:14;159867:9:::3;:30::i;:::-;159936:165;::::0;;::::3;::::0;::::3;::::0;;-1:-1:-1;;;;;159936:165:0;;::::3;::::0;;;;::::3;;::::0;;::::3;::::0;;;::::3;::::0;;::::3;::::0;;;;;;160046:15:::3;159936:165:::0;::::3;::::0;;;;;;-1:-1:-1;159918:15:0;;;:6:::3;:15:::0;;;;;;;:183;;;;;::::3;-1:-1:-1::0;;;159918:183:0::3;::::0;;;::::3;::::0;;;::::3;::::0;;;;;;::::3;::::0;;;;;::::3;-1:-1:-1::0;;;159918:183:0::3;-1:-1:-1::0;;159918:183:0;;;;;;::::3;::::0;;;;;;;::::3;::::0;;160122:41:::3;159972:6:::0;160152:10;160122:21:::3;:41::i;:::-;160189:48;::::0;;-1:-1:-1;;;;;13883:47:1;;13865:66;;13979:10;13967:23;;13962:2;13947:18;;13940:51;160209:7:0;;160197:10:::3;::::0;160189:48:::3;::::0;13838:18:1;160189:48:0::3;;;;;;;158678:1567;;;;;140789:1:::2;138761:20:::0;138155:1;139281:7;:22;139098:213;107163:155;-1:-1:-1;;;;;107275:25:0;;;107251:4;107275:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;107163:155::o;144614:220::-;143567:13;:11;:13::i;:::-;-1:-1:-1;;;;;144699:22:0;::::1;144695:93;;144745:31;::::0;-1:-1:-1;;;144745:31:0;;144773:1:::1;144745:31;::::0;::::1;1488:51:1::0;1461:18;;144745:31:0::1;1342:203:1::0;144695:93:0::1;144798:28;144817:8;144798:18;:28::i;170501:68::-:0;143567:13;:11;:13::i;:::-;170551:10:::1;:8;:10::i;119767:247::-:0;119830:7;109103:16;;;:7;:16;;;;;;-1:-1:-1;;;;;109103:16:0;;119894:90;;119941:31;;-1:-1:-1;;;119941:31:0;;;;;5589:25:1;;;5562:18;;119941:31:0;5443:177:1;117999:122:0;118080:33;118089:2;118093:7;118102:4;118108;118080:8;:33::i;138797:293::-;138199:1;138931:7;;:19;138923:63;;;;-1:-1:-1;;;138923:63:0;;16687:2:1;138923:63:0;;;16669:21:1;16726:2;16706:18;;;16699:30;16765:33;16745:18;;;16738:61;16816:18;;138923:63:0;16485:355:1;138923:63:0;138199:1;139064:7;:18;138797:293::o;141313:108::-;141225:7;;;;141383:9;141375:38;;;;-1:-1:-1;;;141375:38:0;;17047:2:1;141375:38:0;;;17029:21:1;17086:2;17066:18;;;17059:30;-1:-1:-1;;;17105:18:1;;;17098:46;17161:18;;141375:38:0;16845:340:1;150517:363:0;150673:19;:17;:19::i;:::-;150717:12;;150713:160;;150746:115;150781:7;150808:9;150837;150746:16;:115::i;155120:261::-;-1:-1:-1;;;;;155230:18:0;;;;;;:58;;-1:-1:-1;155260:13:0;-1:-1:-1;;;;;155252:36:0;;;155230:58;155226:138;;;155324:28;;-1:-1:-1;;;155324:28:0;;;;;5589:25:1;;;155324:13:0;-1:-1:-1;;;;;155324:19:0;;;;5562:18:1;;155324:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;107385:588::-;-1:-1:-1;;;;;107480:16:0;;107476:89;;107520:33;;-1:-1:-1;;;107520:33:0;;107550:1;107520:33;;;1488:51:1;1461:18;;107520:33:0;1342:203:1;107476:89:0;107786:21;107810:34;107818:2;107822:7;16239:10;107810:7;:34::i;:::-;107786:58;;107876:4;-1:-1:-1;;;;;107859:21:0;:13;-1:-1:-1;;;;;107859:21:0;;107855:111;;107904:50;;-1:-1:-1;;;107904:50:0;;-1:-1:-1;;;;;17410:32:1;;;107904:50:0;;;17392:51:1;17459:18;;;17452:34;;;17522:32;;17502:18;;;17495:60;17365:18;;107904:50:0;17190:371:1;114945:232:0;114997:21;115021:40;115037:1;115041:7;115058:1;115021:7;:40::i;:::-;114997:64;-1:-1:-1;;;;;;115076:27:0;;115072:98;;115127:31;;-1:-1:-1;;;115127:31:0;;;;;5589:25:1;;;5562:18;;115127:31:0;5443:177:1;128179:162:0;128289:43;;-1:-1:-1;;;;;17758:32:1;;;128289:43:0;;;17740:51:1;17807:18;;;17800:34;;;128262:71:0;;128282:5;;128304:14;;;;;17713:18:1;;128289:43:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;128289:43:0;;;;;;;;;;;128262:19;:71::i;143846:166::-;143754:6;;-1:-1:-1;;;;;143754:6:0;;;;;16239:10;143906:23;143902:103;;143953:40;;-1:-1:-1;;;143953:40:0;;16239:10;143953:40;;;1488:51:1;1461:18;;143953:40:0;1342:203:1;144994:191:0;145087:6;;;-1:-1:-1;;;;;145104:17:0;;;145087:6;145104:17;;;-1:-1:-1;;;;;;145104:17:0;;;;;;145137:40;;145087:6;;;;;;;;145137:40;;145068:16;;145137:40;145057:128;144994:191;:::o;164879:801::-;164951:7;164971:22;164996:5;164971:30;;165012:9;146940;;165025;:12;;;:19;;;;:::i;:::-;165024:28;;;;:::i;:::-;165012:40;-1:-1:-1;165078:9:0;165073:460;165097:3;165093:1;:7;165073:460;;;165122:10;146940:9;165122:10;;:::i;:::-;;-1:-1:-1;165147:13:0;165183:6;;;;;;;;165179:119;;;165215:1;165210:6;;165179:119;;;-1:-1:-1;165266:16:0;;;;;;;:12;:16;;;;;;;;165179:119;165368:12;;;;165363:17;;:2;:17;:::i;:::-;165355:26;;165330:9;:15;;;:52;;;;:::i;:::-;165312:70;;:9;;:70;;;;;:::i;:::-;;;;;-1:-1:-1;165401:7:0;;;;;;;;165397:53;;165429:5;;;165397:53;165483:6;165464:9;:15;;:25;;;;;;;:::i;:::-;;;;;-1:-1:-1;;165504:17:0;;;:12;;;:17;165102:3;;165073:460;;;;165566:1;165549:9;:14;;;:18;;;165545:69;;;165601:1;165584:18;;165545:69;-1:-1:-1;165655:14:0;-1:-1:-1;;;;;165639:32:0;;164879:801;-1:-1:-1;;;164879:801:0:o;119206:318::-;-1:-1:-1;;;;;119314:22:0;;119310:93;;119360:31;;-1:-1:-1;;;119360:31:0;;-1:-1:-1;;;;;1506:32:1;;119360:31:0;;;1488:51:1;1461:18;;119360:31:0;1342:203:1;119310:93:0;-1:-1:-1;;;;;119413:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;119413:46:0;;;;;;;;;;119475:41;;540::1;;;119475::0;;513:18:1;119475:41:0;;;;;;;119206:318;;;:::o;108249:236::-;108363:31;108376:4;108382:2;108386:7;108363:12;:31::i;:::-;108405:72;16239:10;108453:4;108459:2;108463:7;108472:4;108405:33;:72::i;114067:102::-;114135:26;114145:2;114149:7;114135:26;;;;;;;;;;;;:9;:26::i;128586:190::-;128714:53;;-1:-1:-1;;;;;18747:32:1;;;128714:53:0;;;18729:51:1;18816:32;;;18796:18;;;18789:60;18865:18;;;18858:34;;;128687:81:0;;128707:5;;128729:18;;;;;18702::1;;128714:53:0;18527:371:1;141750:118:0;140759:19;:17;:19::i;:::-;141810:7:::1;:14:::0;;-1:-1:-1;;141810:14:0::1;141820:4;141810:14;::::0;;141840:20:::1;141847:12;16239:10:::0;;16159:98;141847:12:::1;141840:20;::::0;-1:-1:-1;;;;;1506:32:1;;;1488:51;;1476:2;1461:18;141840:20:0::1;1342:203:1::0;157330:635:0;157481:13;;;146894:8;157610:32;147052:4;146998;157610:32;:::i;:::-;-1:-1:-1;;;;;157591:52:0;157599:6;-1:-1:-1;;;;;157591:15:0;:52;;;;:::i;:::-;157590:64;;;;:::i;:::-;157570:84;-1:-1:-1;;;;;;157669:29:0;;157665:57;;;157707:15;;-1:-1:-1;;;157707:15:0;;;;;;;;;;;157665:57;157749:9;-1:-1:-1;157749:9:0;157858:29;;;;-1:-1:-1;;;;;157858:14:0;;:29;:::i;:::-;157839:49;;147052:4;157839:49;:::i;:::-;157818:71;;157917:13;-1:-1:-1;;;;;157904:26:0;:10;-1:-1:-1;;;;;157904:26:0;;157900:57;;;157939:18;;-1:-1:-1;;;157939:18:0;;;;;;;;;;;157900:57;157516:449;157330:635;;;;;;:::o;157973:470::-;158060:22;158085:37;-1:-1:-1;;;;;158103:19:0;;;;158085:15;;:37;:::i;:::-;158060:62;;158181:10;-1:-1:-1;;;;;158173:19:0;158162:6;-1:-1:-1;;;;;158154:15:0;158137:14;:32;;;;:::i;:::-;:55;158133:85;;158201:17;;-1:-1:-1;;;158201:17:0;;;;;;;;;;;158133:85;158229:30;158262:26;147100:4;158262:14;:26;:::i;:::-;158229:59;-1:-1:-1;;;;;;158303:42:0;;158299:70;;;158354:15;;-1:-1:-1;;;158354:15:0;;;;;;;;;;;158299:70;158380:20;:55;;158412:22;;158380:20;;;:55;;158412:22;;-1:-1:-1;;;;;158380:55:0;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;158380:55:0;;;;;-1:-1:-1;;;;;158380:55:0;;;;;;158049:394;;157973:470;;:::o;142009:120::-;141018:16;:14;:16::i;:::-;142068:7:::1;:15:::0;;-1:-1:-1;;142068:15:0::1;::::0;;142099:22:::1;16239:10:::0;142108:12:::1;16159:98:::0;118309:678;118471:9;:31;;;-1:-1:-1;;;;;;118484:18:0;;;;118471:31;118467:471;;;118519:13;118535:22;118549:7;118535:13;:22::i;:::-;118519:38;-1:-1:-1;;;;;;118688:18:0;;;;;;:35;;;118719:4;-1:-1:-1;;;;;118710:13:0;:5;-1:-1:-1;;;;;118710:13:0;;;118688:35;:69;;;;;118728:29;118745:5;118752:4;118728:16;:29::i;:::-;118727:30;118688:69;118684:144;;;118785:27;;-1:-1:-1;;;118785:27:0;;-1:-1:-1;;;;;1506:32:1;;118785:27:0;;;1488:51:1;1461:18;;118785:27:0;1342:203:1;118684:144:0;118848:9;118844:83;;;118903:7;118899:2;-1:-1:-1;;;;;118883:28:0;118892:5;-1:-1:-1;;;;;118883:28:0;;;;;;;;;;;118844:83;118504:434;118467:471;-1:-1:-1;;118950:24:0;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;118950:29:0;-1:-1:-1;;;;;118950:29:0;;;;;;;;;;118309:678::o;150888:950::-;150953:5;;;;150969:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;150969:22:0;151016:10;;;;151012:289;;151055:12;:24;151068:10;151077:1;151068:6;:10;:::i;:::-;151055:24;;;;;;;;;;;;;;;;;;-1:-1:-1;151055:24:0;151043:36;;;;;;;;;;;;;;;-1:-1:-1;;;151043:36:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;151043:36:0;;;;;;;;;-1:-1:-1;151012:289:0;;;-1:-1:-1;151124:165:0;;;;;;;;-1:-1:-1;151124:165:0;;;;;;;;151213:15;151124:165;;;;;;;;;151260:12;151124:165;;;;;;;151012:289;151337:12;;;;151313:21;151407:40;;;;151414:15;151407:40;;;;151403:198;;;151575:12;;;;151557:30;;;;:15;:30;:::i;:::-;151514:13;;;;151499:28;;;;:12;:28;:::i;:::-;151486:42;;147100:4;151486:42;:::i;:::-;151485:103;;;;:::i;:::-;151464:125;;151403:198;151664:135;151704:9;151728:14;151757:10;151782:6;151664:25;:135::i;:::-;151652:147;-1:-1:-1;151820:10:0;:6;151829:1;151820:10;:::i;:::-;151812:5;:18;;-1:-1:-1;;151812:18:0;;;;;;;;;;;;-1:-1:-1;;;;150888:950:0:o;153130:1160::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;153384:15:0;153361:39;;:9;:13;;;:39;;;:63;;;;;153423:1;153404:9;:16;;;:20;;;153361:63;153357:257;;;153454:16;;:27;;146894:8;;153454:27;:::i;:::-;153441:40;;:10;;;;:40;;;;153561:13;;;:39;;153584:15;;153561:39;:::i;:::-;153553:48;;153508:4;:10;;;:94;;;;:::i;:::-;153496:106;;;;153357:257;153661:15;153638:39;;:9;:13;;;:39;;;:63;;;;;153700:1;153681:9;:16;;;:20;;;153638:63;153634:257;;;153731:16;;:27;;146894:8;;153731:27;:::i;:::-;153718:40;;:10;;;;:40;;;;153838:13;;;:39;;153861:15;;153838:39;:::i;:::-;153830:48;;153785:4;:10;;;:94;;;;:::i;:::-;153773:106;;;;153634:257;153903:134;153943:9;153967;153991:4;:10;;;154016:4;:10;;;153903:25;:134::i;:::-;154050:16;154069:23;;;:14;:23;;;;;;:27;;:23;;;:27;:::i;:::-;154107:23;;;;:14;:23;;;;;;;;:35;;;;;;-1:-1:-1;;154107:35:0;;;;;;;;154170:15;154153:33;;:7;;;:33;;;154215:12;154197:31;;:8;;;:31;;;154239:25;;;:16;:25;;;;;:36;;;;;;;;:43;;;;;;;-1:-1:-1;;;;;154239:43:0;;;-1:-1:-1;;;154239:43:0;;;;;;;;;;154107:35;154239:43;;;;;;;;;;-1:-1:-1;;;154239:43:0;-1:-1:-1;;154239:43:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;;153130:1160:0:o;112209:824::-;112295:7;109103:16;;;:7;:16;;;;;;-1:-1:-1;;;;;109103:16:0;;;;112410:18;;;112406:88;;112445:37;112462:4;112468;112474:7;112445:16;:37::i;:::-;-1:-1:-1;;;;;112541:18:0;;;112537:263;;112659:48;112676:1;112680:7;112697:1;112701:5;112659:8;:48::i;:::-;-1:-1:-1;;;;;112753:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;112753:20:0;;;112537:263;-1:-1:-1;;;;;112816:16:0;;;112812:111;;-1:-1:-1;;;;;112878:13:0;;;;;;:9;:13;;;;;:18;;112895:1;112878:18;;;112812:111;112935:16;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;112935:21:0;-1:-1:-1;;;;;112935:21:0;;;;;;;;;112974:27;;112935:16;;112974:27;;;;;;;113021:4;112209:824;-1:-1:-1;;;;112209:824:0:o;134772:738::-;134853:18;134882:19;135022:4;135019:1;135012:4;135006:11;134999:4;134993;134989:15;134986:1;134979:5;134972;134967:60;135081:7;135071:180;;135126:4;135120:11;135172:16;135169:1;135164:3;135149:40;135219:16;135214:3;135207:29;135071:180;-1:-1:-1;;135330:1:0;135324:8;135279:16;;-1:-1:-1;135359:15:0;;:68;;135411:11;135426:1;135411:16;;135359:68;;;-1:-1:-1;;;;;135377:26:0;;;:31;135359:68;135355:148;;;135451:40;;-1:-1:-1;;;135451:40:0;;-1:-1:-1;;;;;1506:32:1;;135451:40:0;;;1488:51:1;1461:18;;135451:40:0;1342:203:1;14632:948:0;-1:-1:-1;;;;;14819:14:0;;;:18;14815:758;;14858:67;;-1:-1:-1;;;14858:67:0;;-1:-1:-1;;;;;14858:36:0;;;;;:67;;14895:8;;14905:4;;14911:7;;14920:4;;14858:67;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;14858:67:0;;;;;;;;-1:-1:-1;;14858:67:0;;;;;;;;;;;;:::i;:::-;;;14854:708;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15221:6;:13;15238:1;15221:18;15217:330;;15327:39;;-1:-1:-1;;;15327:39:0;;-1:-1:-1;;;;;1506:32:1;;15327:39:0;;;1488:51:1;1461:18;;15327:39:0;1342:203:1;15217:330:0;15497:6;15491:13;15482:6;15478:2;15474:15;15467:38;14854:708;-1:-1:-1;;;;;;14973:51:0;;-1:-1:-1;;;14973:51:0;14969:185;;15095:39;;-1:-1:-1;;;15095:39:0;;-1:-1:-1;;;;;1506:32:1;;15095:39:0;;;1488:51:1;1461:18;;15095:39:0;1342:203:1;14969:185:0;14926:243;14854:708;14632:948;;;;;:::o;114396:210::-;114491:18;114497:2;114501:7;114491:5;:18::i;:::-;114520:78;16239:10;114576:1;114580:2;114584:7;114593:4;114520:33;:78::i;141498:108::-;141225:7;;;;141557:41;;;;-1:-1:-1;;;141557:41:0;;20292:2:1;141557:41:0;;;20274:21:1;20331:2;20311:18;;;20304:30;-1:-1:-1;;;20350:18:1;;;20343:50;20410:18;;141557:41:0;20090:344:1;151846:1276:0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;152081:9:0;152049:29;146940:9;152114:21;146940:9;152114:14;:21;:::i;:::-;152113:30;;;;:::i;:::-;152101:42;-1:-1:-1;152169:9:0;152164:914;152188:3;152184:1;:7;152164:914;;;152213:10;146940:9;152213:10;;:::i;:::-;;-1:-1:-1;152238:13:0;152288:28;152300:15;152288:28;;;;;;152284:163;;;152349:15;152337:28;;152284:163;;;-1:-1:-1;152415:16:0;;;;;;;:12;:16;;;;;;;;152284:163;152526:19;152531:14;152526:2;:19;:::i;:::-;152518:28;;152493:9;:15;;;:54;;;;:::i;:::-;152475:72;;:9;;:72;;;;;:::i;:::-;;;;;-1:-1:-1;152562:15:0;;;:25;;152581:6;;152562:15;:25;;152581:6;;152562:25;:::i;:::-;;;;;-1:-1:-1;152602:17:0;;;:12;;;;:17;;;;152737:19;;;147100:4;;152732:24;;152617:2;152732:24;:::i;:::-;152709:48;;;;-1:-1:-1;;;;;152709:19:0;;:48;:::i;:::-;152708:62;;;;:::i;:::-;152657:16;:20;;;:113;;;;;;:::i;:::-;152634:137;;;;:13;;;:137;152817:15;152804:29;;;;;;152800:219;;-1:-1:-1;152854:36:0;152877:12;152854:36;:13;;;:36;152909:5;;152800:219;152994:9;152955:12;:36;152988:1;152968:10;:6;152977:1;152968:10;:::i;:::-;:22;;;;:::i;:::-;152955:36;;;;;;;;;;;;;;;;;;-1:-1:-1;152955:36:0;:48;;;;;;-1:-1:-1;;;;;152955:48:0;;;-1:-1:-1;;;152955:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;152955:48:0;-1:-1:-1;;152955:48:0;;;;;;;;;;;;;;;;;-1:-1:-1;153064:2:0;;-1:-1:-1;153064:2:0;;152193:3;;152164:914;;;-1:-1:-1;153105:9:0;;151846:1276;-1:-1:-1;;;;;;151846:1276:0:o;154298:814::-;154521:15;154498:39;;:9;:13;;;:39;;;154494:314;;;154586:13;;;;;154573:27;;154554:16;154573:27;;;:12;:27;;;;;;;;;154615:21;154628:8;154573:27;154615:21;:::i;:::-;;;154672:9;:13;;;154655:30;;:9;:13;;;:30;;;154651:92;;154706:21;154719:8;154706:21;;:::i;:::-;;;154651:92;154770:13;;;;;154757:27;;;;;;:12;:27;;;;;;:39;;-1:-1:-1;;;;;;154757:39:0;-1:-1:-1;;;;;154757:39:0;;;;;;;;;;154494:314;154847:15;154824:39;;:9;:13;;;:39;;;154820:285;;;154900:9;:13;;;154884:29;;:9;:13;;;:29;;;154880:214;;;154966:13;;;;;154953:27;;154934:16;154953:27;;;:12;:27;;;;;;;;;154999:21;155012:8;154953:27;154999:21;:::i;:::-;155052:13;;;;;155039:27;;;;;;:12;:27;;;;;;:39;;-1:-1:-1;;;;;155039:39:0;;;-1:-1:-1;;;;;;155039:39:0;;;;;;;;;-1:-1:-1;154298:814:0;;;;:::o;110416:376::-;110529:38;110543:5;110550:7;110559;110529:13;:38::i;:::-;110524:261;;-1:-1:-1;;;;;110588:19:0;;110584:190;;110635:31;;-1:-1:-1;;;110635:31:0;;;;;5589:25:1;;;5562:18;;110635:31:0;5443:177:1;110584:190:0;110714:44;;-1:-1:-1;;;110714:44:0;;-1:-1:-1;;;;;17758:32:1;;110714:44:0;;;17740:51:1;17807:18;;;17800:34;;;17713:18;;110714:44:0;17566:274:1;113369:335:0;-1:-1:-1;;;;;113437:16:0;;113433:89;;113477:33;;-1:-1:-1;;;113477:33:0;;113507:1;113477:33;;;1488:51:1;1461:18;;113477:33:0;1342:203:1;113433:89:0;113532:21;113556:32;113564:2;113568:7;113585:1;113556:7;:32::i;:::-;113532:56;-1:-1:-1;;;;;;113603:27:0;;;113599:98;;113654:31;;-1:-1:-1;;;113654:31:0;;113682:1;113654:31;;;1488:51:1;1461:18;;113654:31:0;1342:203:1;109697:276:0;109800:4;-1:-1:-1;;;;;109837:21:0;;;;;;:128;;;109885:7;-1:-1:-1;;;;;109876:16:0;:5;-1:-1:-1;;;;;109876:16:0;;:52;;;;109896:32;109913:5;109920:7;109896:16;:32::i;:::-;109876:88;;;-1:-1:-1;;109318:7:0;109345:24;;;:15;:24;;;;;;-1:-1:-1;;;;;109345:24:0;;;109932:32;;;;109817:148;-1:-1:-1;109697:276:0: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;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;2033:186::-;2092:6;2145:2;2133:9;2124:7;2120:23;2116:32;2113:52;;;2161:1;2158;2151:12;2113:52;2184:29;2203:9;2184:29;:::i;2224:611::-;2414:2;2426:21;;;2496:13;;2399:18;;;2518:22;;;2366:4;;2597:15;;;2571:2;2556:18;;;2366:4;2640:169;2654:6;2651:1;2648:13;2640:169;;;2715:13;;2703:26;;2758:2;2784:15;;;;2749:12;;;;2676:1;2669:9;2640:169;;;-1:-1:-1;2826:3:1;;2224:611;-1:-1:-1;;;;;2224:611:1:o;2840:163::-;2907:20;;2967:10;2956:22;;2946:33;;2936:61;;2993:1;2990;2983:12;3008:298;3075:6;3083;3136:2;3124:9;3115:7;3111:23;3107:32;3104:52;;;3152:1;3149;3142:12;3104:52;3197:23;;;-1:-1:-1;3263:37:1;3296:2;3281:18;;3263:37;:::i;:::-;3253:47;;3008:298;;;;;:::o;3765:188::-;3833:20;;-1:-1:-1;;;;;3882:46:1;;3872:57;;3862:85;;3943:1;3940;3933:12;3958:493;4043:6;4051;4059;4067;4120:3;4108:9;4099:7;4095:23;4091:33;4088:53;;;4137:1;4134;4127:12;4088:53;4182:23;;;-1:-1:-1;4248:37:1;4281:2;4266:18;;4248:37;:::i;:::-;4238:47;-1:-1:-1;4358:2:1;4343:18;;4330:32;;-1:-1:-1;4407:38:1;4441:2;4426:18;;4407:38;:::i;:::-;4397:48;;3958:493;;;;;;;:::o;4456:374::-;4533:6;4541;4549;4602:2;4590:9;4581:7;4577:23;4573:32;4570:52;;;4618:1;4615;4608:12;4570:52;4641:29;4660:9;4641:29;:::i;:::-;4631:39;;4689:38;4723:2;4712:9;4708:18;4689:38;:::i;:::-;4456:374;;4679:48;;-1:-1:-1;;;4796:2:1;4781:18;;;;4768:32;;4456:374::o;5058:184::-;5116:6;5169:2;5157:9;5148:7;5144:23;5140:32;5137:52;;;5185:1;5182;5175:12;5137:52;5208:28;5226:9;5208:28;:::i;6519:347::-;6584:6;6592;6645:2;6633:9;6624:7;6620:23;6616:32;6613:52;;;6661:1;6658;6651:12;6613:52;6684:29;6703:9;6684:29;:::i;:::-;6674:39;;6763:2;6752:9;6748:18;6735:32;6810:5;6803:13;6796:21;6789:5;6786:32;6776:60;;6832:1;6829;6822:12;6776:60;6855:5;6845:15;;;6519:347;;;;;:::o;6871:127::-;6932:10;6927:3;6923:20;6920:1;6913:31;6963:4;6960:1;6953:15;6987:4;6984:1;6977:15;7003:275;7074:2;7068:9;7139:2;7120:13;;-1:-1:-1;;7116:27:1;7104:40;;7174:18;7159:34;;7195:22;;;7156:62;7153:88;;;7221:18;;:::i;:::-;7257:2;7250:22;7003:275;;-1:-1:-1;7003:275:1:o;7283:186::-;7331:4;7364:18;7356:6;7353:30;7350:56;;;7386:18;;:::i;:::-;-1:-1:-1;7452:2:1;7431:15;-1:-1:-1;;7427:29:1;7458:4;7423:40;;7283:186::o;7474:958::-;7569:6;7577;7585;7593;7646:3;7634:9;7625:7;7621:23;7617:33;7614:53;;;7663:1;7660;7653:12;7614:53;7686:29;7705:9;7686:29;:::i;:::-;7676:39;;7734:38;7768:2;7757:9;7753:18;7734:38;:::i;:::-;7724:48;-1:-1:-1;7841:2:1;7826:18;;7813:32;;-1:-1:-1;7920:2:1;7905:18;;7892:32;7947:18;7936:30;;7933:50;;;7979:1;7976;7969:12;7933:50;8002:22;;8055:4;8047:13;;8043:27;-1:-1:-1;8033:55:1;;8084:1;8081;8074:12;8033:55;8124:2;8111:16;8149:52;8165:35;8193:6;8165:35;:::i;:::-;8149:52;:::i;:::-;8224:6;8217:5;8210:21;8272:7;8267:2;8258:6;8254:2;8250:15;8246:24;8243:37;8240:57;;;8293:1;8290;8283:12;8240:57;8348:6;8343:2;8339;8335:11;8330:2;8323:5;8319:14;8306:49;8400:1;8395:2;8386:6;8379:5;8375:18;8371:27;8364:38;8421:5;8411:15;;;;;7474:958;;;;;;;:::o;8437:730::-;8532:6;8540;8548;8601:2;8589:9;8580:7;8576:23;8572:32;8569:52;;;8617:1;8614;8607:12;8569:52;8657:9;8644:23;8690:18;8682:6;8679:30;8676:50;;;8722:1;8719;8712:12;8676:50;8745:22;;8798:4;8790:13;;8786:27;-1:-1:-1;8776:55:1;;8827:1;8824;8817:12;8776:55;8867:2;8854:16;8893:18;8885:6;8882:30;8879:50;;;8925:1;8922;8915:12;8879:50;8980:7;8973:4;8963:6;8960:1;8956:14;8952:2;8948:23;8944:34;8941:47;8938:67;;;9001:1;8998;8991:12;8938:67;9032:4;9024:13;;;;9056:6;;-1:-1:-1;9116:20:1;;9103:34;;8437:730;-1:-1:-1;;;8437:730:1:o;9172:495::-;9258:6;9266;9274;9282;9335:3;9323:9;9314:7;9310:23;9306:33;9303:53;;;9352:1;9349;9342:12;9303:53;9397:23;;;-1:-1:-1;9463:38:1;9497:2;9482:18;;9463:38;:::i;9672:258::-;9739:6;9747;9800:2;9788:9;9779:7;9775:23;9771:32;9768:52;;;9816:1;9813;9806:12;9768:52;9839:29;9858:9;9839:29;:::i;:::-;9829:39;;9887:37;9920:2;9909:9;9905:18;9887:37;:::i;9935:447::-;10020:6;10028;10036;10044;10097:3;10085:9;10076:7;10072:23;10068:33;10065:53;;;10114:1;10111;10104:12;10065:53;10137:29;10156:9;10137:29;:::i;:::-;10127:39;;10185:37;10218:2;10207:9;10203:18;10185:37;:::i;10387:260::-;10455:6;10463;10516:2;10504:9;10495:7;10491:23;10487:32;10484:52;;;10532:1;10529;10522:12;10484:52;10555:29;10574:9;10555:29;:::i;:::-;10545:39;;10603:38;10637:2;10626:9;10622:18;10603:38;:::i;10652:380::-;10731:1;10727:12;;;;10774;;;10795:61;;10849:4;10841:6;10837:17;10827:27;;10795:61;10902:2;10894:6;10891:14;10871:18;10868:38;10865:161;;10948:10;10943:3;10939:20;10936:1;10929:31;10983:4;10980:1;10973:15;11011:4;11008:1;11001:15;10865:161;;10652:380;;;:::o;11037:127::-;11098:10;11093:3;11089:20;11086:1;11079:31;11129:4;11126:1;11119:15;11153:4;11150:1;11143:15;11169:127;11230:10;11225:3;11221:20;11218:1;11211:31;11261:4;11258:1;11251:15;11285:4;11282:1;11275:15;11301:135;11340:3;11361:17;;;11358:43;;11381:18;;:::i;:::-;-1:-1:-1;11428:1:1;11417:13;;11301:135::o;11441:167::-;11536:10;11509:18;;;11529;;;11505:43;;11560:19;;11557:45;;;11582:18;;:::i;11613:243::-;-1:-1:-1;;;;;11728:42:1;;;11684;;;11680:91;;11783:44;;11780:70;;;11830:18;;:::i;11861:168::-;11934:9;;;11965;;11982:15;;;11976:22;;11962:37;11952:71;;12003:18;;:::i;12034:127::-;12095:10;12090:3;12086:20;12083:1;12076:31;12126:4;12123:1;12116:15;12150:4;12147:1;12140:15;12166:120;12206:1;12232;12222:35;;12237:18;;:::i;:::-;-1:-1:-1;12271:9:1;;12166:120::o;12291:125::-;12356:9;;;12377:10;;;12374:36;;;12390:18;;:::i;12421:240::-;-1:-1:-1;;;;;12490:42:1;;;12534;;;12486:91;;12589:43;;12586:69;;;12635:18;;:::i;13325:170::-;13422:10;13415:18;;;13395;;;13391:43;;13446:20;;13443:46;;;13469:18;;:::i;13500:188::-;13538:3;13582:10;13575:5;13571:22;13617:10;13608:7;13605:23;13602:49;;13631:18;;:::i;:::-;13680:1;13667:15;;13500:188;-1:-1:-1;;13500:188:1:o;14002:184::-;14072:6;14125:2;14113:9;14104:7;14100:23;14096:32;14093:52;;;14141:1;14138;14131:12;14093:52;-1:-1:-1;14164:16:1;;14002:184;-1:-1:-1;14002:184:1:o;14638:301::-;14767:3;14805:6;14799:13;14851:6;14844:4;14836:6;14832:17;14827:3;14821:37;14913:1;14877:16;;14902:13;;;-1:-1:-1;14877:16:1;14638:301;-1:-1:-1;14638:301:1:o;15294:686::-;15374:6;15427:2;15415:9;15406:7;15402:23;15398:32;15395:52;;;15443:1;15440;15433:12;15395:52;15476:9;15470:16;15509:18;15501:6;15498:30;15495:50;;;15541:1;15538;15531:12;15495:50;15564:22;;15617:4;15609:13;;15605:27;-1:-1:-1;15595:55:1;;15646:1;15643;15636:12;15595:55;15679:2;15673:9;15704:52;15720:35;15748:6;15720:35;:::i;15704:52::-;15779:6;15772:5;15765:21;15827:7;15822:2;15813:6;15809:2;15805:15;15801:24;15798:37;15795:57;;;15848:1;15845;15838:12;15795:57;15896:6;15891:2;15887;15883:11;15878:2;15871:5;15867:14;15861:42;15948:1;15923:18;;;15943:2;15919:27;15912:38;;;;15927:5;15294:686;-1:-1:-1;;;;15294:686:1:o;15985:241::-;16024:7;16103:1;16099:2;16088:17;16084:1;16080:2;16069:17;16065:41;16141:11;16137:2;16126:27;16115:38;;16184:11;16175:7;16172:24;16162:58;;16200:18;;:::i;:::-;16162:58;15985:241;;;;:::o;16231:249::-;16331:2;16320:17;;;16301;;;;16297:41;-1:-1:-1;;;;;;16353:50:1;;-1:-1:-1;;;;;16405:45:1;;16350:101;16347:127;;;16454:18;;:::i;17845:178::-;17884:1;17918:10;17915:1;17911:18;17948:3;17938:37;;17955:18;;:::i;:::-;18013:3;18000:10;17997:1;17993:18;17989:28;17984:33;;;17845:178;;;;:::o;18028:244::-;18139:10;18112:18;;;18132;;;18108:43;18171:28;;;;18218:24;;;18208:58;;18246:18;;:::i;18277:245::-;18375:2;18345:17;;;18364;;;;18341:41;-1:-1:-1;;;;;18397:44:1;;-1:-1:-1;;;;;;18443:49:1;;18394:99;18391:125;;;18496:18;;:::i;18903:128::-;18970:9;;;18991:11;;;18988:37;;;19005:18;;:::i;19036:305::-;19075:1;19117;19113:2;19102:17;19154:1;19150:2;19139:17;19175:3;19165:37;;19182:18;;:::i;:::-;-1:-1:-1;;;;;;19218:48:1;;-1:-1:-1;;19268:15:1;;19214:70;19211:96;;;19287:18;;:::i;:::-;19321:14;;;19036:305;-1:-1:-1;;;19036:305:1:o;19346:485::-;-1:-1:-1;;;;;19577:32:1;;;19559:51;;19646:32;;19641:2;19626:18;;19619:60;19710:2;19695:18;;19688:34;;;19758:3;19753:2;19738:18;;19731:31;;;-1:-1:-1;;19779:46:1;;19805:19;;19797:6;19779:46;:::i;19836:249::-;19905:6;19958:2;19946:9;19937:7;19933:23;19929:32;19926:52;;;19974:1;19971;19964:12;19926:52;20006:9;20000:16;20025:30;20049:5;20025:30;:::i
Swarm Source
ipfs://3b6888d2732bfd5dcfd7dcb20ed792bd78ab3c61911802ab6ecfffddb0d63076
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
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.