Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 7 from a total of 7 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Emergency Withdr... | 7896804 | 4 days ago | IN | 0 S | 0.00361448 | ||||
Enable Emergency... | 7890631 | 5 days ago | IN | 0 S | 0.00196187 | ||||
Withdraw | 7890473 | 5 days ago | IN | 0 S | 0.00490997 | ||||
Create Lock | 7883548 | 5 days ago | IN | 0 S | 0.01040811 | ||||
Create Lock | 7873990 | 5 days ago | IN | 0 S | 0.01230876 | ||||
Set Art Proxy | 7873367 | 5 days ago | IN | 0 S | 0.00167852 | ||||
Un Pause | 7873287 | 5 days ago | IN | 0 S | 0.00160612 |
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 SonicScan.org on 2025-02-14 */ // 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(); 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) private _locks; mapping(address => uint8) private _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 ); 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; } 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) * multiplier) / PRECISION; _totalWeightedSupply -= uint128(weightedAmount); _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 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; // Calculate slope with safe math uint256 slopeCalc = (uint256(amount) * (MAX_MULTIPLIER - BASE_MULTIPLIER)) / MAXTIME; if (slopeCalc > type(uint128).max) revert InvalidAmount(); uint128 slope = uint128(slopeCalc); // Verify minimum multiplier uint128 multiplier = uint128(BASE_MULTIPLIER + (uint256(slope) * lockDuration)); if (multiplier < minMultiplier) revert SlippageExceeded(); // 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 }); uint256 weightedSupplyIncrease = (uint256(amount) * multiplier) / PRECISION; if (weightedSupplyIncrease > type(uint128).max) revert InvalidAmount(); _totalWeightedSupply += uint128(weightedSupplyIncrease); emit Deposit(msg.sender, tokenId, amount, unlockTime); } 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 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)); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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":"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":"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":"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":"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"}],"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":"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":"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":[],"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
60c0604052600f805463ffffffff60a01b1916600f60a01b179055348015610025575f5ffd5b50604051613b72380380613b728339810160408190526100449161033c565b3382825f6100528382610456565b50600161005f8282610456565b50506001600655506007805460ff191690556001600160a01b03811661009f57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100a881610189565b506001600160a01b03851615806100c657506001600160a01b038416155b806100d857506001600160a01b038316155b156100f65760405163d92e233d60e01b815260040160405180910390fd5b6100fe6101e2565b50506001600160a01b0392831660805290821660a052601180546001600160a01b031916919092161790555f8052600a6020527f13da86008ba1c6922daee3e07db95305ef49ebced9f5467a0b8613fcc6b343e480546001600160401b0319166401000000004363ffffffff9081169190910263ffffffff1916919091174291909116179055610510565b600780546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6101ea61023c565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861021f3390565b6040516001600160a01b03909116815260200160405180910390a1565b60075460ff16156102825760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610096565b565b80516001600160a01b038116811461029a575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126102c2575f5ffd5b81516001600160401b038111156102db576102db61029f565b604051601f8201601f19908116603f011681016001600160401b03811182821017156103095761030961029f565b604052818152838201602001851015610320575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f5f5f5f60a08688031215610350575f5ffd5b61035986610284565b945061036760208701610284565b935061037560408701610284565b60608701519093506001600160401b03811115610390575f5ffd5b61039c888289016102b3565b608088015190935090506001600160401b038111156103b9575f5ffd5b6103c5888289016102b3565b9150509295509295909350565b600181811c908216806103e657607f821691505b60208210810361040457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561045157805f5260205f20601f840160051c8101602085101561042f5750805b601f840160051c820191505b8181101561044e575f815560010161043b565b50505b505050565b81516001600160401b0381111561046f5761046f61029f565b6104838161047d84546103d2565b8461040a565b6020601f8211600181146104b5575f831561049e5750848201515b5f19600385901b1c1916600184901b17845561044e565b5f84815260208120601f198516915b828110156104e457878501518255602094850194600190920191016104c4565b508482101561050157868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b60805160a05161361e6105545f395f8181611d4b0152611d9101525f818161099001528181610bb8015281816118980152818161191c015261197c015261361e5ff3fe608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638b25e8c11161012a578063bbe33ea5116100b4578063df21515711610079578063df215157146105b0578063e58f5947146105c3578063e985e9c5146105e8578063f2fde38b146105fb578063f7b188a51461060e575f5ffd5b8063bbe33ea51461055c578063c5b1c7d01461056f578063c87b56dd14610577578063ddacc94a1461058a578063df0c78ef1461059d575f5ffd5b806395d89b41116100fa57806395d89b41146104de57806397612d4b146104e65780639b7d02ad146104f9578063a22cb46514610536578063b88d4fde14610549575f5ffd5b80638b25e8c1146104495780638da5cb5b1461045c5780638ff4249014610472578063900cf0cf146104b9575f5ffd5b80632e720f7d116101ab578063586c26001161017b578063586c2600146103cd5780635c975abb146104025780636352211e1461040d57806370a0823114610420578063715018a614610441575f5ffd5b80632e720f7d1461038157806342842e0e146103945780635312ea8e146103a75780635594a045146103ba575f5ffd5b80631d237a49116101f15780631d237a491461029f57806320a194b81461032457806323b872dd14610336578063268dc199146103495780632e1a7d4d1461036e575f5ffd5b806301ffc9a71461022257806306fdde031461024a578063081812fc1461025f578063095ea7b31461028a575b5f5ffd5b610235610230366004612ecd565b610616565b60405190151581526020015b60405180910390f35b610252610667565b6040516102419190612f16565b61027261026d366004612f28565b6106f6565b6040516001600160a01b039091168152602001610241565b61029d610298366004612f5a565b61071d565b005b6102f16102ad366004612f95565b600d60209081525f928352604080842090915290825290208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b60408051600f95860b81529390940b602084015263ffffffff918216938301939093529091166060820152608001610241565b601154600160a01b900460ff16610235565b61029d610344366004612fbf565b61072c565b6010546001600160801b03165b6040516001600160801b039091168152602001610241565b61029d61037c366004612f28565b610746565b61029d61038f366004612ff9565b610a13565b61029d6103a2366004612fbf565b610a64565b61029d6103b5366004612f28565b610a7e565b600f54610272906001600160a01b031681565b6103ef6103db366004613012565b600e6020525f9081526040902054600f0b81565b604051600f9190910b8152602001610241565b60075460ff16610235565b61027261041b366004612f28565b610c34565b61043361042e366004612ff9565b610c3e565b604051908152602001610241565b61029d610c83565b610356610457366004612f28565b610c96565b60075461010090046001600160a01b0316610272565b6102f1610480366004613012565b600a6020525f908152604090208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b600b546104c99063ffffffff1681565b60405163ffffffff9091168152602001610241565b610252610d48565b6103566104f4366004613012565b610d57565b610524610507366004612ff9565b6001600160a01b03165f9081526009602052604090205460ff1690565b60405160ff9091168152602001610241565b61029d61054436600461302b565b610dc3565b61029d6105573660046130d0565b610dce565b61029d61056a366004613174565b610dea565b61029d611340565b610252610585366004612f28565b6113a6565b610356610598366004612f95565b6114f5565b6103566105ab3660046131ff565b6115d2565b6104336105be366004613227565b611690565b6104c96105d1366004612f28565b600c6020525f908152604090205463ffffffff1681565b6102356105f6366004613271565b611c7a565b61029d610609366004612ff9565b611ca7565b61029d611ce1565b5f6001600160e01b031982166380ac58cd60e01b148061064657506001600160e01b03198216635b5e139f60e01b145b8061066157506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f805461067590613299565b80601f01602080910402602001604051908101604052809291908181526020018280546106a190613299565b80156106ec5780601f106106c3576101008083540402835291602001916106ec565b820191905f5260205f20905b8154815290600101906020018083116106cf57829003601f168201915b5050505050905090565b5f61070082611cf1565b505f828152600460205260409020546001600160a01b0316610661565b610728828233611d29565b5050565b6107368382611d36565b610741838383611e03565b505050565b61074e611e86565b5f818152600260205260409020546001600160a01b03168061078257604051626f708760e21b815260040160405180910390fd5b6001600160a01b03811633146107ab576040516359dc379f60e01b815260040160405180910390fd5b5f828152600860209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b90049091166060820152910361082657604051632254ea3d60e11b815260040160405180910390fd5b806040015163ffffffff164263ffffffff1610156108575760405163342ad40160e11b815260040160405180910390fd5b8051604080518082018252600f83900b81528184015163ffffffff166020808301919091525f8781526008909152918220828155600101805467ffffffffffffffff19169055906108a786610c96565b90505f670de0b6b3a76400006108c96001600160801b038085169087166132e5565b6108d39190613310565b6010805491925082915f906108f29084906001600160801b0316613323565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555061093e878460405180604001604052805f600f0b81526020015f63ffffffff16815250611edf565b5f878152600c60205260409020805463ffffffff1916905561095f87611ef8565b335f818152600960205260409020805460ff19811660ff9182165f19019091161790556109c0906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906001600160801b038716611f30565b6040516001600160801b0385168152879033907f8903a5b5d08a841e7f68438387f1da20c84dea756379ed37e633ff3854b99b849060200160405180910390a3505050505050610a106001600655565b50565b610a1b611f8f565b6001600160a01b038116610a425760405163d92e233d60e01b815260040160405180910390fd5b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b61074183838360405180602001604052805f815250610dce565b610a86611e86565b601154600160a01b900460ff16610adc5760405162461bcd60e51b81526020600482015260156024820152744e6f7420696e20656d657267656e6379206d6f646560581b60448201526064015b60405180910390fd5b33610ae682610c34565b6001600160a01b031614610b0d576040516359dc379f60e01b815260040160405180910390fd5b5f818152600860208181526040808420815160808101835281546001600160801b03808216808452600160801b909204168286015260018301805463ffffffff80821696850196909652600160201b810490951660608401528888529590945294905567ffffffffffffffff1916909155610b8783611ef8565b335f818152600960205260409020805460ff19811660ff9182165f1901909116179055610be8906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906001600160801b038416611f30565b6040516001600160801b0382168152839033907f4f27eb511b2a4633cfb633ac1c4a99b4c298ca6488b29ec26f3504a5927f67289060200160405180910390a35050610a106001600655565b5f61066182611cf1565b5f6001600160a01b038216610c68576040516322718ad960e21b81525f6004820152602401610ad3565b506001600160a01b03165f9081526003602052604090205490565b610c8b611f8f565b610c945f611fc2565b565b5f818152600860209081526040808320815160808101835281546001600160801b038082168352600160801b90910416938101939093526001015463ffffffff808216928401839052600160201b90910481166060840152421610610d055750670de0b6b3a764000092915050565b5f4282604001510390508063ffffffff1682602001516001600160801b0316610d2e91906132e5565b610d4090670de0b6b3a7640000613342565b949350505050565b60606001805461067590613299565b600b5463ffffffff9081165f908152600a6020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001015480851691830191909152600160201b9004909216606083015290610dbc818461201b565b9392505050565b610728338383612130565b610dd88483611d36565b610de4848484846121ce565b50505050565b610df2611e86565b610dfa6121e6565b8080421115610e1c57604051631ab7da6b60e01b815260040160405180910390fd5b6002831015610e3e5760405163162908e360e11b815260040160405180910390fd5b5f80805b85811015610f475733610e6c888884818110610e6057610e60613355565b90506020020135610c34565b6001600160a01b031614610e93576040516359dc379f60e01b815260040160405180910390fd5b5f60085f898985818110610ea957610ea9613355565b602090810292909201358352508181019290925260409081015f20815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b900490911660608201529150610f1c9085613369565b93508263ffffffff16816040015163ffffffff161115610f3e57806040015192505b50600101610e42565b505f610f534283613388565b905062ed4e0063ffffffff82161115610f7f57604051637616640160e01b815260040160405180910390fd5b5f62ed4e00610f9e670de0b6b3a7640000673782dace9d900000613323565b6001600160801b0316856001600160801b0316610fbb91906132e5565b610fc59190613310565b90506001600160801b03811115610fef5760405163162908e360e11b815260040160405180910390fd5b6007805482915f9160159061101090600160a81b900463ffffffff166133a4565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff16905061103f338261222c565b5f5b8981101561112a575f8b8b8381811061105c5761105c613355565b602090810292909201355f818152600884526040808220815160808101835281546001600160801b038082168352600160801b909104168188015260019091015463ffffffff808216838501908152600160201b90920481166060840152835180850185528351600f0b8152915116818801528251808401909352838352958201929092529194509291506110f49084908390611edf565b5f838152600860205260408120908155600101805467ffffffffffffffff1916905561111f83611ef8565b505050600101611041565b50604080518082018252600f88900b815263ffffffff871660208083019190915282518084019093525f808452908301529061116890839083611edf565b6040518060800160405280886001600160801b03168152602001846001600160801b031681526020018763ffffffff1681526020014263ffffffff1681525060085f8481526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055509050508a8a905060095f336001600160a01b03166001600160a01b031681526020019081526020015f205f9054906101000a900460ff160360010160095f336001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081336001600160a01b03167fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f859782893495489896040516113269291906001600160801b0392909216825263ffffffff16602082015260400190565b60405180910390a350505050505050506107416001600655565b611348611f8f565b6011805460ff60a01b1916600160a01b179055611363612245565b6011546040516001600160a01b0390911681527fc0a1c7e9f05b4d536e1ff8606bae9b847cdb43ef4a9b2d7a503a88cee08dccdb906020015b60405180910390a1565b5f818152600260205260409020546060906001600160a01b03166113dc57604051626f708760e21b815260040160405180910390fd5b600f546001600160a01b0316611405576040516338a69c8d60e21b815260040160405180910390fd5b600f54604051602481018490525f9182916001600160a01b039091169060440160408051601f198184030181529181526020820180516001600160e01b031663c87b56dd60e01b1790525161145a91906133c8565b5f60405180830381855afa9150503d805f8114611492576040519150601f19603f3d011682016040523d82523d5f602084013e611497565b606091505b5091509150816114e15760405162461bcd60e51b8152602060048201526015602482015274105c9d081c1c9bde1e4818d85b1b0819985a5b1959605a1b6044820152606401610ad3565b80806020019051810190610d4091906133de565b5f828152600c602052604081205463ffffffff16808203611519575f915050610661565b5f848152600d6020908152604080832063ffffffff80861685529083529281902081516080810183528154600f81810b8352600160801b909104900b9381019390935260010154808416918301829052600160201b90049092166060820152906115839085613388565b63ffffffff1681602001516115989190613453565b815182906115a7908390613479565b600f90810b90915282515f910b121590506115c0575f81525b516001600160801b0316949350505050565b600f545f90819063ffffffff600160a01b9091048116908416116115f65782611610565b600f5461161090600160a01b900463ffffffff1684613388565b90505f62ed4e00611631670de0b6b3a7640000673782dace9d900000613323565b6001600160801b0316866001600160801b031661164e91906132e5565b6116589190613310565b90508061167463ffffffff84166001600160801b0383166132e5565b61168690670de0b6b3a7640000613342565b9695505050505050565b5f611699611e86565b6116a16121e6565b82804211156116c357604051631ab7da6b60e01b815260040160405180910390fd5b856001600160801b03165f036116ec5760405163162908e360e11b815260040160405180910390fd5b63ffffffff85161580611707575062ed4e0063ffffffff8616115b1561172557604051637616640160e01b815260040160405180910390fd5b335f90815260096020526040902054606460ff909116106117595760405163133cbc4f60e01b815260040160405180910390fd5b5f61176486426134a6565b90505f62ed4e00611785670de0b6b3a7640000673782dace9d900000613323565b6001600160801b0316896001600160801b03166117a291906132e5565b6117ac9190613310565b90506001600160801b038111156117d65760405163162908e360e11b815260040160405180910390fd5b805f6117f163ffffffff8a166001600160801b0384166132e5565b61180390670de0b6b3a7640000613342565b9050866001600160801b0316816001600160801b0316101561183857604051638199f5f360e01b815260040160405180910390fd5b5f60405180604001604052808c600f0b81526020018663ffffffff1681525090506118815f60405180604001604052805f600f0b81526020015f63ffffffff1681525083611edf565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118e5573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061190991906134c2565b905061195433308e6001600160801b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661229a909392919063ffffffff16565b6119676001600160801b038d1682613342565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156119c9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ed91906134c2565b14611a0b576040516312171d8360e31b815260040160405180910390fd5b60078054600163ffffffff600160a81b80840482168381019092160263ffffffff60a81b1990931692909217909255335f818152600960205260409020805460ff80821690950190941660ff19909416939093179092559850611a6e908961222c565b60405180608001604052808d6001600160801b03168152602001856001600160801b031681526020018763ffffffff1681526020014263ffffffff1681525060085f8a81526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055509050505f670de0b6b3a76400006001600160801b0316846001600160801b03168e6001600160801b0316611b9591906132e5565b611b9f9190613310565b90506001600160801b03811115611bc95760405163162908e360e11b815260040160405180910390fd5b601080548291905f90611be69084906001600160801b0316613369565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555088336001600160a01b03167fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f85978289349548f8a604051611c609291906001600160801b0392909216825263ffffffff16602082015260400190565b60405180910390a35050505050505050610d406001600655565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b611caf611f8f565b6001600160a01b038116611cd857604051631e4fbdf760e01b81525f6004820152602401610ad3565b610a1081611fc2565b611ce9611f8f565b610c946122d3565b5f818152600260205260408120546001600160a01b03168061066157604051637e27328960e01b815260048101849052602401610ad3565b610741838383600161230c565b6001600160a01b03821615801590611d7657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615155b156107285760405163379607f560e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063379607f5906024016020604051808303815f875af1158015611ddf573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061074191906134c2565b6001600160a01b038216611e2c57604051633250574960e11b81525f6004820152602401610ad3565b5f611e38838333612410565b9050836001600160a01b0316816001600160a01b031614610de4576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610ad3565b600260065403611ed85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ad3565b6002600655565b611ee7612502565b821561074157610741838383612668565b5f611f045f835f612410565b90506001600160a01b03811661072857604051637e27328960e01b815260048101839052602401610ad3565b6040516001600160a01b0383811660248301526044820183905261074191859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061285e565b6007546001600160a01b03610100909104163314610c945760405163118cdaa760e01b8152336004820152602401610ad3565b600780546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f5f8390505f62093a8080836040015161203591906134d9565b61203f9190613500565b90505f5b60ff81101561210b5761205962093a80836134a6565b91505f63ffffffff80871690841611156120755785925061208f565b5063ffffffff82165f908152600e6020526040902054600f0b5b604084015161209e9084613388565b63ffffffff1684602001516120b39190613453565b845185906120c2908390613479565b600f0b90525063ffffffff808716908416036120de575061210b565b80846020018181516120f0919061351f565b600f0b9052505063ffffffff82166040840152600101612043565b505f825f0151600f0b121561211e575f82525b50516001600160801b03169392505050565b6001600160a01b03821661216257604051630b61174360e31b81526001600160a01b0383166004820152602401610ad3565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6121d984848461072c565b610de433858585856128ca565b60075460ff1615610c945760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ad3565b610728828260405180602001604052805f8152506129f2565b61224d6121e6565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586122823390565b6040516001600160a01b03909116815260200161139c565b6040516001600160a01b038481166024830152838116604483015260648201839052610de49186918216906323b872dd90608401611f5d565b6122db612a09565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612282565b808061232057506001600160a01b03821615155b156123e1575f61232f84611cf1565b90506001600160a01b0383161580159061235b5750826001600160a01b0316816001600160a01b031614155b801561236e575061236c8184611c7a565b155b156123975760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610ad3565b81156123df5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b5f828152600260205260408120546001600160a01b039081169083161561243c5761243c818486612a52565b6001600160a01b03811615612476576124575f855f5f61230c565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b038516156124a4576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b600b5463ffffffff16612534604080516080810182525f80825260208201819052918101829052606081019190915290565b63ffffffff8216156125ad57600a5f61254e600185613388565b63ffffffff908116825260208083019390935260409182015f2082516080810184528154600f81810b8352600160801b909104900b948101949094526001015480821692840192909252600160201b90910416606082015290506125da565b50604080516080810182525f808252602082015263ffffffff428116928201929092524390911660608201525b60408101515f63ffffffff80831642909116111561263b5760408301516126079063ffffffff164261354c565b606084015161261c9063ffffffff164361354c565b61262e90670de0b6b3a76400006132e5565b6126389190613310565b90505b61264783838387612ab6565b5050600b805463ffffffff191663ffffffff94909416939093179092555050565b604080516080810182525f808252602082018190529181018290526060810191909152604080516080810182525f8082526020820181905291810182905260608101919091524263ffffffff16846020015163ffffffff161180156126d257505f845f0151600f0b135b1561271c5783516126e79062ed4e009061355f565b600f0b602080840191909152840151612701904290613388565b63ffffffff1682602001516127169190613453565b600f0b82525b4263ffffffff16836020015163ffffffff1611801561274057505f835f0151600f0b135b1561278a5782516127559062ed4e009061355f565b600f0b60208083019190915283015161276f904290613388565b63ffffffff1681602001516127849190613453565b600f0b81525b61279e848484602001518460200151612cbb565b5f858152600c60205260408120546127bd9063ffffffff1660016134a6565b5f878152600c60209081526040808320805463ffffffff95861663ffffffff199091168117909155428516878301908152438616606089019081529b8552600d84528285209185529083529220855195909101516001600160801b03908116600160801b02951694909417845551600193909301805497518216600160201b0267ffffffffffffffff19909816939091169290921795909517905550505050565b5f5f60205f8451602086015f885af18061287d576040513d5f823e3d81fd5b50505f513d915081156128945780600114156128a1565b6001600160a01b0384163b155b15610de457604051635274afe760e01b81526001600160a01b0385166004820152602401610ad3565b6001600160a01b0383163b156129eb57604051630a85bd0160e11b81526001600160a01b0384169063150b7a029061290c90889088908790879060040161359b565b6020604051808303815f875af1925050508015612946575060408051601f3d908101601f19168201909252612943918101906135cd565b60015b6129ad573d808015612973576040519150601f19603f3d011682016040523d82523d5f602084013e612978565b606091505b5080515f036129a557604051633250574960e11b81526001600160a01b0385166004820152602401610ad3565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b146129e957604051633250574960e11b81526001600160a01b0385166004820152602401610ad3565b505b5050505050565b6129fc8383612df6565b610741335f8585856128ca565b60075460ff16610c945760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610ad3565b612a5d838383612e57565b610741576001600160a01b038316612a8b57604051637e27328960e01b815260048101829052602401610ad3565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610ad3565b604080516080810182525f808252602082018190529181018290526060810191909152845f62093a80612ae981886134d9565b612af39190613500565b90505f5b60ff811015612caf57612b0d62093a80836134a6565b91505f63ffffffff4281169084161115612b2957429250612b43565b5063ffffffff82165f908152600e6020526040902054600f0b5b612b4d8884613388565b63ffffffff168960200151612b629190613453565b89518a90612b71908390613479565b600f0b905250602089018051829190612b8b90839061351f565b600f0b90525063ffffffff83166040808b0191909152840151670de0b6b3a764000090612bb89085613388565b612bd19063ffffffff166001600160801b038a166132e5565b612bdb9190613310565b846060015163ffffffff16612bf09190613342565b63ffffffff90811660608b015242811690841603612c1a575063ffffffff43166060890152612caf565b88600a5f84612c2a8a60016134a6565b612c3491906134a6565b63ffffffff908116825260208083019390935260409182015f208451938501516001600160801b03908116600160801b02941693909317835590830151600190920180546060909401518216600160201b0267ffffffffffffffff199094169290911691909117919091179055509095508590600101612af7565b50959695505050505050565b4263ffffffff16846020015163ffffffff161115612d5c5760208085015163ffffffff165f908152600e9091526040902054600f0b612cfa838261351f565b9050846020015163ffffffff16846020015163ffffffff1603612d2457612d218282613479565b90505b60208581015163ffffffff165f908152600e9091526040902080546001600160801b0319166001600160801b03929092169190911790555b4263ffffffff16836020015163ffffffff161115610de457836020015163ffffffff16836020015163ffffffff161115610de45760208084015163ffffffff165f908152600e9091526040902054600f0b612db78282613479565b60208086015163ffffffff165f908152600e9091526040902080546001600160801b039092166001600160801b03199092169190911790555050505050565b6001600160a01b038216612e1f57604051633250574960e11b81525f6004820152602401610ad3565b5f612e2b83835f612410565b90506001600160a01b03811615610741576040516339e3563760e11b81525f6004820152602401610ad3565b5f6001600160a01b03831615801590610d405750826001600160a01b0316846001600160a01b03161480612e905750612e908484611c7a565b80610d405750505f908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b031981168114610a10575f5ffd5b5f60208284031215612edd575f5ffd5b8135610dbc81612eb8565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610dbc6020830184612ee8565b5f60208284031215612f38575f5ffd5b5035919050565b80356001600160a01b0381168114612f55575f5ffd5b919050565b5f5f60408385031215612f6b575f5ffd5b612f7483612f3f565b946020939093013593505050565b803563ffffffff81168114612f55575f5ffd5b5f5f60408385031215612fa6575f5ffd5b82359150612fb660208401612f82565b90509250929050565b5f5f5f60608486031215612fd1575f5ffd5b612fda84612f3f565b9250612fe860208501612f3f565b929592945050506040919091013590565b5f60208284031215613009575f5ffd5b610dbc82612f3f565b5f60208284031215613022575f5ffd5b610dbc82612f82565b5f5f6040838503121561303c575f5ffd5b61304583612f3f565b915060208301358015158114613059575f5ffd5b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130a1576130a1613064565b604052919050565b5f67ffffffffffffffff8211156130c2576130c2613064565b50601f01601f191660200190565b5f5f5f5f608085870312156130e3575f5ffd5b6130ec85612f3f565b93506130fa60208601612f3f565b925060408501359150606085013567ffffffffffffffff81111561311c575f5ffd5b8501601f8101871361312c575f5ffd5b803561313f61313a826130a9565b613078565b818152886020838501011115613153575f5ffd5b816020840160208301375f6020838301015280935050505092959194509250565b5f5f5f60408486031215613186575f5ffd5b833567ffffffffffffffff81111561319c575f5ffd5b8401601f810186136131ac575f5ffd5b803567ffffffffffffffff8111156131c2575f5ffd5b8660208260051b84010111156131d6575f5ffd5b6020918201979096509401359392505050565b80356001600160801b0381168114612f55575f5ffd5b5f5f60408385031215613210575f5ffd5b613219836131e9565b9150612fb660208401612f82565b5f5f5f5f6080858703121561323a575f5ffd5b613243856131e9565b935061325160208601612f82565b925060408501359150613266606086016131e9565b905092959194509250565b5f5f60408385031215613282575f5ffd5b61328b83612f3f565b9150612fb660208401612f3f565b600181811c908216806132ad57607f821691505b6020821081036132cb57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610661576106616132d1565b634e487b7160e01b5f52601260045260245ffd5b5f8261331e5761331e6132fc565b500490565b6001600160801b038281168282160390811115610661576106616132d1565b80820180821115610661576106616132d1565b634e487b7160e01b5f52603260045260245ffd5b6001600160801b038181168382160190811115610661576106616132d1565b63ffffffff8281168282160390811115610661576106616132d1565b5f63ffffffff821663ffffffff81036133bf576133bf6132d1565b60010192915050565b5f82518060208501845e5f920191825250919050565b5f602082840312156133ee575f5ffd5b815167ffffffffffffffff811115613404575f5ffd5b8201601f81018413613414575f5ffd5b805161342261313a826130a9565b818152856020838501011115613436575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f82600f0b82600f0b0280600f0b9150808214613472576134726132d1565b5092915050565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610661576106616132d1565b63ffffffff8181168382160190811115610661576106616132d1565b5f602082840312156134d2575f5ffd5b5051919050565b5f63ffffffff8316806134ee576134ee6132fc565b8063ffffffff84160491505092915050565b63ffffffff8181168382160290811690818114613472576134726132d1565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610661576106616132d1565b81810381811115610661576106616132d1565b5f81600f0b83600f0b80613575576135756132fc565b60016001607f1b031982145f1982141615613592576135926132d1565b90059392505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f9061168690830184612ee8565b5f602082840312156135dd575f5ffd5b8151610dbc81612eb856fea2646970667358221220fb0bea65dd5a26c1473f6c42b5f1881f29b1295416b1db4abcf930bc5a3cc81764736f6c634300081b003300000000000000000000000094b999e05d1361a802ad6690c1b1ae3426a4e1a6000000000000000000000000004705281735aca71681c82157f553c395066cc30000000000000000000000005b14cc6b2a36a7c36de709775252855d0563e0a500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000b4661726d20457363726f7700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057665534958000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638b25e8c11161012a578063bbe33ea5116100b4578063df21515711610079578063df215157146105b0578063e58f5947146105c3578063e985e9c5146105e8578063f2fde38b146105fb578063f7b188a51461060e575f5ffd5b8063bbe33ea51461055c578063c5b1c7d01461056f578063c87b56dd14610577578063ddacc94a1461058a578063df0c78ef1461059d575f5ffd5b806395d89b41116100fa57806395d89b41146104de57806397612d4b146104e65780639b7d02ad146104f9578063a22cb46514610536578063b88d4fde14610549575f5ffd5b80638b25e8c1146104495780638da5cb5b1461045c5780638ff4249014610472578063900cf0cf146104b9575f5ffd5b80632e720f7d116101ab578063586c26001161017b578063586c2600146103cd5780635c975abb146104025780636352211e1461040d57806370a0823114610420578063715018a614610441575f5ffd5b80632e720f7d1461038157806342842e0e146103945780635312ea8e146103a75780635594a045146103ba575f5ffd5b80631d237a49116101f15780631d237a491461029f57806320a194b81461032457806323b872dd14610336578063268dc199146103495780632e1a7d4d1461036e575f5ffd5b806301ffc9a71461022257806306fdde031461024a578063081812fc1461025f578063095ea7b31461028a575b5f5ffd5b610235610230366004612ecd565b610616565b60405190151581526020015b60405180910390f35b610252610667565b6040516102419190612f16565b61027261026d366004612f28565b6106f6565b6040516001600160a01b039091168152602001610241565b61029d610298366004612f5a565b61071d565b005b6102f16102ad366004612f95565b600d60209081525f928352604080842090915290825290208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b60408051600f95860b81529390940b602084015263ffffffff918216938301939093529091166060820152608001610241565b601154600160a01b900460ff16610235565b61029d610344366004612fbf565b61072c565b6010546001600160801b03165b6040516001600160801b039091168152602001610241565b61029d61037c366004612f28565b610746565b61029d61038f366004612ff9565b610a13565b61029d6103a2366004612fbf565b610a64565b61029d6103b5366004612f28565b610a7e565b600f54610272906001600160a01b031681565b6103ef6103db366004613012565b600e6020525f9081526040902054600f0b81565b604051600f9190910b8152602001610241565b60075460ff16610235565b61027261041b366004612f28565b610c34565b61043361042e366004612ff9565b610c3e565b604051908152602001610241565b61029d610c83565b610356610457366004612f28565b610c96565b60075461010090046001600160a01b0316610272565b6102f1610480366004613012565b600a6020525f908152604090208054600190910154600f82810b92600160801b9004900b9063ffffffff80821691600160201b90041684565b600b546104c99063ffffffff1681565b60405163ffffffff9091168152602001610241565b610252610d48565b6103566104f4366004613012565b610d57565b610524610507366004612ff9565b6001600160a01b03165f9081526009602052604090205460ff1690565b60405160ff9091168152602001610241565b61029d61054436600461302b565b610dc3565b61029d6105573660046130d0565b610dce565b61029d61056a366004613174565b610dea565b61029d611340565b610252610585366004612f28565b6113a6565b610356610598366004612f95565b6114f5565b6103566105ab3660046131ff565b6115d2565b6104336105be366004613227565b611690565b6104c96105d1366004612f28565b600c6020525f908152604090205463ffffffff1681565b6102356105f6366004613271565b611c7a565b61029d610609366004612ff9565b611ca7565b61029d611ce1565b5f6001600160e01b031982166380ac58cd60e01b148061064657506001600160e01b03198216635b5e139f60e01b145b8061066157506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f805461067590613299565b80601f01602080910402602001604051908101604052809291908181526020018280546106a190613299565b80156106ec5780601f106106c3576101008083540402835291602001916106ec565b820191905f5260205f20905b8154815290600101906020018083116106cf57829003601f168201915b5050505050905090565b5f61070082611cf1565b505f828152600460205260409020546001600160a01b0316610661565b610728828233611d29565b5050565b6107368382611d36565b610741838383611e03565b505050565b61074e611e86565b5f818152600260205260409020546001600160a01b03168061078257604051626f708760e21b815260040160405180910390fd5b6001600160a01b03811633146107ab576040516359dc379f60e01b815260040160405180910390fd5b5f828152600860209081526040808320815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b90049091166060820152910361082657604051632254ea3d60e11b815260040160405180910390fd5b806040015163ffffffff164263ffffffff1610156108575760405163342ad40160e11b815260040160405180910390fd5b8051604080518082018252600f83900b81528184015163ffffffff166020808301919091525f8781526008909152918220828155600101805467ffffffffffffffff19169055906108a786610c96565b90505f670de0b6b3a76400006108c96001600160801b038085169087166132e5565b6108d39190613310565b6010805491925082915f906108f29084906001600160801b0316613323565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555061093e878460405180604001604052805f600f0b81526020015f63ffffffff16815250611edf565b5f878152600c60205260409020805463ffffffff1916905561095f87611ef8565b335f818152600960205260409020805460ff19811660ff9182165f19019091161790556109c0906001600160a01b037f00000000000000000000000094b999e05d1361a802ad6690c1b1ae3426a4e1a616906001600160801b038716611f30565b6040516001600160801b0385168152879033907f8903a5b5d08a841e7f68438387f1da20c84dea756379ed37e633ff3854b99b849060200160405180910390a3505050505050610a106001600655565b50565b610a1b611f8f565b6001600160a01b038116610a425760405163d92e233d60e01b815260040160405180910390fd5b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b61074183838360405180602001604052805f815250610dce565b610a86611e86565b601154600160a01b900460ff16610adc5760405162461bcd60e51b81526020600482015260156024820152744e6f7420696e20656d657267656e6379206d6f646560581b60448201526064015b60405180910390fd5b33610ae682610c34565b6001600160a01b031614610b0d576040516359dc379f60e01b815260040160405180910390fd5b5f818152600860208181526040808420815160808101835281546001600160801b03808216808452600160801b909204168286015260018301805463ffffffff80821696850196909652600160201b810490951660608401528888529590945294905567ffffffffffffffff1916909155610b8783611ef8565b335f818152600960205260409020805460ff19811660ff9182165f1901909116179055610be8906001600160a01b037f00000000000000000000000094b999e05d1361a802ad6690c1b1ae3426a4e1a616906001600160801b038416611f30565b6040516001600160801b0382168152839033907f4f27eb511b2a4633cfb633ac1c4a99b4c298ca6488b29ec26f3504a5927f67289060200160405180910390a35050610a106001600655565b5f61066182611cf1565b5f6001600160a01b038216610c68576040516322718ad960e21b81525f6004820152602401610ad3565b506001600160a01b03165f9081526003602052604090205490565b610c8b611f8f565b610c945f611fc2565b565b5f818152600860209081526040808320815160808101835281546001600160801b038082168352600160801b90910416938101939093526001015463ffffffff808216928401839052600160201b90910481166060840152421610610d055750670de0b6b3a764000092915050565b5f4282604001510390508063ffffffff1682602001516001600160801b0316610d2e91906132e5565b610d4090670de0b6b3a7640000613342565b949350505050565b60606001805461067590613299565b600b5463ffffffff9081165f908152600a6020908152604080832081516080810183528154600f81810b8352600160801b909104900b938101939093526001015480851691830191909152600160201b9004909216606083015290610dbc818461201b565b9392505050565b610728338383612130565b610dd88483611d36565b610de4848484846121ce565b50505050565b610df2611e86565b610dfa6121e6565b8080421115610e1c57604051631ab7da6b60e01b815260040160405180910390fd5b6002831015610e3e5760405163162908e360e11b815260040160405180910390fd5b5f80805b85811015610f475733610e6c888884818110610e6057610e60613355565b90506020020135610c34565b6001600160a01b031614610e93576040516359dc379f60e01b815260040160405180910390fd5b5f60085f898985818110610ea957610ea9613355565b602090810292909201358352508181019290925260409081015f20815160808101835281546001600160801b03808216808452600160801b909204169482019490945260019091015463ffffffff80821693830193909352600160201b900490911660608201529150610f1c9085613369565b93508263ffffffff16816040015163ffffffff161115610f3e57806040015192505b50600101610e42565b505f610f534283613388565b905062ed4e0063ffffffff82161115610f7f57604051637616640160e01b815260040160405180910390fd5b5f62ed4e00610f9e670de0b6b3a7640000673782dace9d900000613323565b6001600160801b0316856001600160801b0316610fbb91906132e5565b610fc59190613310565b90506001600160801b03811115610fef5760405163162908e360e11b815260040160405180910390fd5b6007805482915f9160159061101090600160a81b900463ffffffff166133a4565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff16905061103f338261222c565b5f5b8981101561112a575f8b8b8381811061105c5761105c613355565b602090810292909201355f818152600884526040808220815160808101835281546001600160801b038082168352600160801b909104168188015260019091015463ffffffff808216838501908152600160201b90920481166060840152835180850185528351600f0b8152915116818801528251808401909352838352958201929092529194509291506110f49084908390611edf565b5f838152600860205260408120908155600101805467ffffffffffffffff1916905561111f83611ef8565b505050600101611041565b50604080518082018252600f88900b815263ffffffff871660208083019190915282518084019093525f808452908301529061116890839083611edf565b6040518060800160405280886001600160801b03168152602001846001600160801b031681526020018763ffffffff1681526020014263ffffffff1681525060085f8481526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055509050508a8a905060095f336001600160a01b03166001600160a01b031681526020019081526020015f205f9054906101000a900460ff160360010160095f336001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548160ff021916908360ff16021790555081336001600160a01b03167fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f859782893495489896040516113269291906001600160801b0392909216825263ffffffff16602082015260400190565b60405180910390a350505050505050506107416001600655565b611348611f8f565b6011805460ff60a01b1916600160a01b179055611363612245565b6011546040516001600160a01b0390911681527fc0a1c7e9f05b4d536e1ff8606bae9b847cdb43ef4a9b2d7a503a88cee08dccdb906020015b60405180910390a1565b5f818152600260205260409020546060906001600160a01b03166113dc57604051626f708760e21b815260040160405180910390fd5b600f546001600160a01b0316611405576040516338a69c8d60e21b815260040160405180910390fd5b600f54604051602481018490525f9182916001600160a01b039091169060440160408051601f198184030181529181526020820180516001600160e01b031663c87b56dd60e01b1790525161145a91906133c8565b5f60405180830381855afa9150503d805f8114611492576040519150601f19603f3d011682016040523d82523d5f602084013e611497565b606091505b5091509150816114e15760405162461bcd60e51b8152602060048201526015602482015274105c9d081c1c9bde1e4818d85b1b0819985a5b1959605a1b6044820152606401610ad3565b80806020019051810190610d4091906133de565b5f828152600c602052604081205463ffffffff16808203611519575f915050610661565b5f848152600d6020908152604080832063ffffffff80861685529083529281902081516080810183528154600f81810b8352600160801b909104900b9381019390935260010154808416918301829052600160201b90049092166060820152906115839085613388565b63ffffffff1681602001516115989190613453565b815182906115a7908390613479565b600f90810b90915282515f910b121590506115c0575f81525b516001600160801b0316949350505050565b600f545f90819063ffffffff600160a01b9091048116908416116115f65782611610565b600f5461161090600160a01b900463ffffffff1684613388565b90505f62ed4e00611631670de0b6b3a7640000673782dace9d900000613323565b6001600160801b0316866001600160801b031661164e91906132e5565b6116589190613310565b90508061167463ffffffff84166001600160801b0383166132e5565b61168690670de0b6b3a7640000613342565b9695505050505050565b5f611699611e86565b6116a16121e6565b82804211156116c357604051631ab7da6b60e01b815260040160405180910390fd5b856001600160801b03165f036116ec5760405163162908e360e11b815260040160405180910390fd5b63ffffffff85161580611707575062ed4e0063ffffffff8616115b1561172557604051637616640160e01b815260040160405180910390fd5b335f90815260096020526040902054606460ff909116106117595760405163133cbc4f60e01b815260040160405180910390fd5b5f61176486426134a6565b90505f62ed4e00611785670de0b6b3a7640000673782dace9d900000613323565b6001600160801b0316896001600160801b03166117a291906132e5565b6117ac9190613310565b90506001600160801b038111156117d65760405163162908e360e11b815260040160405180910390fd5b805f6117f163ffffffff8a166001600160801b0384166132e5565b61180390670de0b6b3a7640000613342565b9050866001600160801b0316816001600160801b0316101561183857604051638199f5f360e01b815260040160405180910390fd5b5f60405180604001604052808c600f0b81526020018663ffffffff1681525090506118815f60405180604001604052805f600f0b81526020015f63ffffffff1681525083611edf565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000094b999e05d1361a802ad6690c1b1ae3426a4e1a66001600160a01b0316906370a0823190602401602060405180830381865afa1580156118e5573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061190991906134c2565b905061195433308e6001600160801b03167f00000000000000000000000094b999e05d1361a802ad6690c1b1ae3426a4e1a66001600160a01b031661229a909392919063ffffffff16565b6119676001600160801b038d1682613342565b6040516370a0823160e01b81523060048201527f00000000000000000000000094b999e05d1361a802ad6690c1b1ae3426a4e1a66001600160a01b0316906370a0823190602401602060405180830381865afa1580156119c9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ed91906134c2565b14611a0b576040516312171d8360e31b815260040160405180910390fd5b60078054600163ffffffff600160a81b80840482168381019092160263ffffffff60a81b1990931692909217909255335f818152600960205260409020805460ff80821690950190941660ff19909416939093179092559850611a6e908961222c565b60405180608001604052808d6001600160801b03168152602001856001600160801b031681526020018763ffffffff1681526020014263ffffffff1681525060085f8a81526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055509050505f670de0b6b3a76400006001600160801b0316846001600160801b03168e6001600160801b0316611b9591906132e5565b611b9f9190613310565b90506001600160801b03811115611bc95760405163162908e360e11b815260040160405180910390fd5b601080548291905f90611be69084906001600160801b0316613369565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555088336001600160a01b03167fdbd81f1b10e6f1395ede56cabac59119f8be0cb5ca3ef0ca44f85978289349548f8a604051611c609291906001600160801b0392909216825263ffffffff16602082015260400190565b60405180910390a35050505050505050610d406001600655565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b611caf611f8f565b6001600160a01b038116611cd857604051631e4fbdf760e01b81525f6004820152602401610ad3565b610a1081611fc2565b611ce9611f8f565b610c946122d3565b5f818152600260205260408120546001600160a01b03168061066157604051637e27328960e01b815260048101849052602401610ad3565b610741838383600161230c565b6001600160a01b03821615801590611d7657507f000000000000000000000000004705281735aca71681c82157f553c395066cc36001600160a01b031615155b156107285760405163379607f560e01b8152600481018290527f000000000000000000000000004705281735aca71681c82157f553c395066cc36001600160a01b03169063379607f5906024016020604051808303815f875af1158015611ddf573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061074191906134c2565b6001600160a01b038216611e2c57604051633250574960e11b81525f6004820152602401610ad3565b5f611e38838333612410565b9050836001600160a01b0316816001600160a01b031614610de4576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610ad3565b600260065403611ed85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610ad3565b6002600655565b611ee7612502565b821561074157610741838383612668565b5f611f045f835f612410565b90506001600160a01b03811661072857604051637e27328960e01b815260048101839052602401610ad3565b6040516001600160a01b0383811660248301526044820183905261074191859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061285e565b6007546001600160a01b03610100909104163314610c945760405163118cdaa760e01b8152336004820152602401610ad3565b600780546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f5f8390505f62093a8080836040015161203591906134d9565b61203f9190613500565b90505f5b60ff81101561210b5761205962093a80836134a6565b91505f63ffffffff80871690841611156120755785925061208f565b5063ffffffff82165f908152600e6020526040902054600f0b5b604084015161209e9084613388565b63ffffffff1684602001516120b39190613453565b845185906120c2908390613479565b600f0b90525063ffffffff808716908416036120de575061210b565b80846020018181516120f0919061351f565b600f0b9052505063ffffffff82166040840152600101612043565b505f825f0151600f0b121561211e575f82525b50516001600160801b03169392505050565b6001600160a01b03821661216257604051630b61174360e31b81526001600160a01b0383166004820152602401610ad3565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6121d984848461072c565b610de433858585856128ca565b60075460ff1615610c945760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ad3565b610728828260405180602001604052805f8152506129f2565b61224d6121e6565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586122823390565b6040516001600160a01b03909116815260200161139c565b6040516001600160a01b038481166024830152838116604483015260648201839052610de49186918216906323b872dd90608401611f5d565b6122db612a09565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612282565b808061232057506001600160a01b03821615155b156123e1575f61232f84611cf1565b90506001600160a01b0383161580159061235b5750826001600160a01b0316816001600160a01b031614155b801561236e575061236c8184611c7a565b155b156123975760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610ad3565b81156123df5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b5f828152600260205260408120546001600160a01b039081169083161561243c5761243c818486612a52565b6001600160a01b03811615612476576124575f855f5f61230c565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b038516156124a4576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b600b5463ffffffff16612534604080516080810182525f80825260208201819052918101829052606081019190915290565b63ffffffff8216156125ad57600a5f61254e600185613388565b63ffffffff908116825260208083019390935260409182015f2082516080810184528154600f81810b8352600160801b909104900b948101949094526001015480821692840192909252600160201b90910416606082015290506125da565b50604080516080810182525f808252602082015263ffffffff428116928201929092524390911660608201525b60408101515f63ffffffff80831642909116111561263b5760408301516126079063ffffffff164261354c565b606084015161261c9063ffffffff164361354c565b61262e90670de0b6b3a76400006132e5565b6126389190613310565b90505b61264783838387612ab6565b5050600b805463ffffffff191663ffffffff94909416939093179092555050565b604080516080810182525f808252602082018190529181018290526060810191909152604080516080810182525f8082526020820181905291810182905260608101919091524263ffffffff16846020015163ffffffff161180156126d257505f845f0151600f0b135b1561271c5783516126e79062ed4e009061355f565b600f0b602080840191909152840151612701904290613388565b63ffffffff1682602001516127169190613453565b600f0b82525b4263ffffffff16836020015163ffffffff1611801561274057505f835f0151600f0b135b1561278a5782516127559062ed4e009061355f565b600f0b60208083019190915283015161276f904290613388565b63ffffffff1681602001516127849190613453565b600f0b81525b61279e848484602001518460200151612cbb565b5f858152600c60205260408120546127bd9063ffffffff1660016134a6565b5f878152600c60209081526040808320805463ffffffff95861663ffffffff199091168117909155428516878301908152438616606089019081529b8552600d84528285209185529083529220855195909101516001600160801b03908116600160801b02951694909417845551600193909301805497518216600160201b0267ffffffffffffffff19909816939091169290921795909517905550505050565b5f5f60205f8451602086015f885af18061287d576040513d5f823e3d81fd5b50505f513d915081156128945780600114156128a1565b6001600160a01b0384163b155b15610de457604051635274afe760e01b81526001600160a01b0385166004820152602401610ad3565b6001600160a01b0383163b156129eb57604051630a85bd0160e11b81526001600160a01b0384169063150b7a029061290c90889088908790879060040161359b565b6020604051808303815f875af1925050508015612946575060408051601f3d908101601f19168201909252612943918101906135cd565b60015b6129ad573d808015612973576040519150601f19603f3d011682016040523d82523d5f602084013e612978565b606091505b5080515f036129a557604051633250574960e11b81526001600160a01b0385166004820152602401610ad3565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b146129e957604051633250574960e11b81526001600160a01b0385166004820152602401610ad3565b505b5050505050565b6129fc8383612df6565b610741335f8585856128ca565b60075460ff16610c945760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610ad3565b612a5d838383612e57565b610741576001600160a01b038316612a8b57604051637e27328960e01b815260048101829052602401610ad3565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610ad3565b604080516080810182525f808252602082018190529181018290526060810191909152845f62093a80612ae981886134d9565b612af39190613500565b90505f5b60ff811015612caf57612b0d62093a80836134a6565b91505f63ffffffff4281169084161115612b2957429250612b43565b5063ffffffff82165f908152600e6020526040902054600f0b5b612b4d8884613388565b63ffffffff168960200151612b629190613453565b89518a90612b71908390613479565b600f0b905250602089018051829190612b8b90839061351f565b600f0b90525063ffffffff83166040808b0191909152840151670de0b6b3a764000090612bb89085613388565b612bd19063ffffffff166001600160801b038a166132e5565b612bdb9190613310565b846060015163ffffffff16612bf09190613342565b63ffffffff90811660608b015242811690841603612c1a575063ffffffff43166060890152612caf565b88600a5f84612c2a8a60016134a6565b612c3491906134a6565b63ffffffff908116825260208083019390935260409182015f208451938501516001600160801b03908116600160801b02941693909317835590830151600190920180546060909401518216600160201b0267ffffffffffffffff199094169290911691909117919091179055509095508590600101612af7565b50959695505050505050565b4263ffffffff16846020015163ffffffff161115612d5c5760208085015163ffffffff165f908152600e9091526040902054600f0b612cfa838261351f565b9050846020015163ffffffff16846020015163ffffffff1603612d2457612d218282613479565b90505b60208581015163ffffffff165f908152600e9091526040902080546001600160801b0319166001600160801b03929092169190911790555b4263ffffffff16836020015163ffffffff161115610de457836020015163ffffffff16836020015163ffffffff161115610de45760208084015163ffffffff165f908152600e9091526040902054600f0b612db78282613479565b60208086015163ffffffff165f908152600e9091526040902080546001600160801b039092166001600160801b03199092169190911790555050505050565b6001600160a01b038216612e1f57604051633250574960e11b81525f6004820152602401610ad3565b5f612e2b83835f612410565b90506001600160a01b03811615610741576040516339e3563760e11b81525f6004820152602401610ad3565b5f6001600160a01b03831615801590610d405750826001600160a01b0316846001600160a01b03161480612e905750612e908484611c7a565b80610d405750505f908152600460205260409020546001600160a01b03908116911614919050565b6001600160e01b031981168114610a10575f5ffd5b5f60208284031215612edd575f5ffd5b8135610dbc81612eb8565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610dbc6020830184612ee8565b5f60208284031215612f38575f5ffd5b5035919050565b80356001600160a01b0381168114612f55575f5ffd5b919050565b5f5f60408385031215612f6b575f5ffd5b612f7483612f3f565b946020939093013593505050565b803563ffffffff81168114612f55575f5ffd5b5f5f60408385031215612fa6575f5ffd5b82359150612fb660208401612f82565b90509250929050565b5f5f5f60608486031215612fd1575f5ffd5b612fda84612f3f565b9250612fe860208501612f3f565b929592945050506040919091013590565b5f60208284031215613009575f5ffd5b610dbc82612f3f565b5f60208284031215613022575f5ffd5b610dbc82612f82565b5f5f6040838503121561303c575f5ffd5b61304583612f3f565b915060208301358015158114613059575f5ffd5b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156130a1576130a1613064565b604052919050565b5f67ffffffffffffffff8211156130c2576130c2613064565b50601f01601f191660200190565b5f5f5f5f608085870312156130e3575f5ffd5b6130ec85612f3f565b93506130fa60208601612f3f565b925060408501359150606085013567ffffffffffffffff81111561311c575f5ffd5b8501601f8101871361312c575f5ffd5b803561313f61313a826130a9565b613078565b818152886020838501011115613153575f5ffd5b816020840160208301375f6020838301015280935050505092959194509250565b5f5f5f60408486031215613186575f5ffd5b833567ffffffffffffffff81111561319c575f5ffd5b8401601f810186136131ac575f5ffd5b803567ffffffffffffffff8111156131c2575f5ffd5b8660208260051b84010111156131d6575f5ffd5b6020918201979096509401359392505050565b80356001600160801b0381168114612f55575f5ffd5b5f5f60408385031215613210575f5ffd5b613219836131e9565b9150612fb660208401612f82565b5f5f5f5f6080858703121561323a575f5ffd5b613243856131e9565b935061325160208601612f82565b925060408501359150613266606086016131e9565b905092959194509250565b5f5f60408385031215613282575f5ffd5b61328b83612f3f565b9150612fb660208401612f3f565b600181811c908216806132ad57607f821691505b6020821081036132cb57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610661576106616132d1565b634e487b7160e01b5f52601260045260245ffd5b5f8261331e5761331e6132fc565b500490565b6001600160801b038281168282160390811115610661576106616132d1565b80820180821115610661576106616132d1565b634e487b7160e01b5f52603260045260245ffd5b6001600160801b038181168382160190811115610661576106616132d1565b63ffffffff8281168282160390811115610661576106616132d1565b5f63ffffffff821663ffffffff81036133bf576133bf6132d1565b60010192915050565b5f82518060208501845e5f920191825250919050565b5f602082840312156133ee575f5ffd5b815167ffffffffffffffff811115613404575f5ffd5b8201601f81018413613414575f5ffd5b805161342261313a826130a9565b818152856020838501011115613436575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f82600f0b82600f0b0280600f0b9150808214613472576134726132d1565b5092915050565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610661576106616132d1565b63ffffffff8181168382160190811115610661576106616132d1565b5f602082840312156134d2575f5ffd5b5051919050565b5f63ffffffff8316806134ee576134ee6132fc565b8063ffffffff84160491505092915050565b63ffffffff8181168382160290811690818114613472576134726132d1565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610661576106616132d1565b81810381811115610661576106616132d1565b5f81600f0b83600f0b80613575576135756132fc565b60016001607f1b031982145f1982141615613592576135926132d1565b90059392505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f9061168690830184612ee8565b5f602082840312156135dd575f5ffd5b8151610dbc81612eb856fea2646970667358221220fb0bea65dd5a26c1473f6c42b5f1881f29b1295416b1db4abcf930bc5a3cc81764736f6c634300081b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000094b999e05d1361a802ad6690c1b1ae3426a4e1a6000000000000000000000000004705281735aca71681c82157f553c395066cc30000000000000000000000005b14cc6b2a36a7c36de709775252855d0563e0a500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000b4661726d20457363726f7700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057665534958000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : lockedToken (address): 0x94B999e05D1361A802aD6690c1b1aE3426A4e1a6
Arg [1] : distributor (address): 0x004705281735AcA71681C82157F553c395066Cc3
Arg [2] : emergencyRecovery (address): 0x5B14Cc6b2a36a7c36dE709775252855d0563E0A5
Arg [3] : name (string): Farm Escrow
Arg [4] : symbol (string): veSIX
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 00000000000000000000000094b999e05d1361a802ad6690c1b1ae3426a4e1a6
Arg [1] : 000000000000000000000000004705281735aca71681c82157f553c395066cc3
Arg [2] : 0000000000000000000000005b14cc6b2a36a7c36de709775252855d0563e0a5
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [6] : 4661726d20457363726f77000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [8] : 7665534958000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
145697:20169: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;:::-;;147714:68;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;147714:68:0;;;;;;;;;;-1:-1:-1;;;147714:68:0;;;;;;;;;2756:2:1;2745:22;;;2727:41;;2804:22;;;;2799:2;2784:18;;2777:50;2875:10;2863:23;;;2843:18;;;2836:51;;;;2923:23;;;2918:2;2903:18;;2896:51;2714:3;2699:19;147714:68:0;2504:449:1;164997:96:0;165071:14;;-1:-1:-1;;;165071:14:0;;;;164997:96;;155009:191;;;;;;:::i;:::-;;:::i;165101:109::-;165182:20;;-1:-1:-1;;;;;165182:20:0;165101:109;;;-1:-1:-1;;;;;3501:47:1;;;3483:66;;3471:2;3456:18;165101:109:0;3337:218:1;155446:1231:0;;;;;;:::i;:::-;;:::i;165218:146::-;;;;;;:::i;:::-;;:::i;108044:134::-;;;;;;:::i;:::-;;:::i;164180:586::-;;;;;;:::i;:::-;;:::i;147841:23::-;;;;;-1:-1:-1;;;;;147841:23:0;;;147789:45;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;4113:2:1;4102:22;;;;4084:41;;4072:2;4057:18;147789:45:0;3940:191:1;141158:86:0;141229:7;;;;141158:86;;105357:120;;;;;;:::i;:::-;;:::i;105082:213::-;;;;;;:::i;:::-;;:::i;:::-;;;4282:25:1;;;4270:2;4255:18;105082:213:0;4136:177:1;144360:103:0;;;:::i;149707:425::-;;;;;;:::i;:::-;;:::i;143685:87::-;143758:6;;;;;-1:-1:-1;;;;;143758:6:0;143685:87;;147582:44;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;147582:44:0;;;;;;;;;;-1:-1:-1;;;147582:44:0;;;;;147633:19;;;;;;;;;;;;4492:10:1;4480:23;;;4462:42;;4450:2;4435:18;147633:19:0;4318:192:1;105704:95:0;;;:::i;158945:199::-;;;;;;:::i;:::-;;:::i;164873:116::-;;;;;;:::i;:::-;-1:-1:-1;;;;;164961:20:0;164936:5;164961:20;;;:14;:20;;;;;;;;;164873:116;;;;4687:4:1;4675:17;;;4657:36;;4645:2;4630:18;164873:116:0;4515:184:1;106946:146:0;;;;;;:::i;:::-;;:::i;155208:226::-;;;;;;:::i;:::-;;:::i;160408:2544::-;;;;;;:::i;:::-;;:::i;164000:172::-;;;:::i;165368:495::-;;;;;;:::i;:::-;;:::i;162960:490::-;;;;;;:::i;:::-;;:::i;163458:506::-;;;;;;:::i;:::-;;:::i;156685:2252::-;;;;;;:::i;:::-;;:::i;147659:48::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;107163:155;;;;;;:::i;:::-;;:::i;144618:220::-;;;;;;:::i;:::-;;:::i;164774: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;155009:191::-;155109:35;155130:4;155136:7;155109:20;:35::i;:::-;155155:36;155174:4;155179:2;155183:7;155155:18;:36::i;:::-;155009:191;;;:::o;155446:1231::-;138721:21;:19;:21::i;:::-;155514:13:::1;109103:16:::0;;;:7;:16;;;;;;-1:-1:-1;;;;;109103:16:0;;155558:48:::1;;155590:16;;-1:-1:-1::0;;;155590:16:0::1;;;;;;;;;;;155558:48;-1:-1:-1::0;;;;;155621:19:0;::::1;155630:10;155621:19;155617:47;;155649:15;;-1:-1:-1::0;;;155649:15:0::1;;;;;;;;;;;155617:47;155685:24;155712:15:::0;;;:6:::1;:15;::::0;;;;;;;155685:42;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;155685:42:0;;::::1;::::0;;;-1:-1:-1;;;155685:42:0;;::::1;;::::0;;::::1;::::0;;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;155685:42:0;::::1;::::0;;::::1;::::0;;;;;155742:16;155738:44:::1;;155767:15;;-1:-1:-1::0;;;155767:15:0::1;;;;;;;;;;;155738:44;155823:4;:12;;;155797:38;;155804:15;155797:38;;;155793:67;;;155844:16;;-1:-1:-1::0;;;155844:16:0::1;;;;;;;;;;;155793:67;155898:11:::0;;155961:104:::1;::::0;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;156041:12;;::::1;::::0;155961:104:::1;;;::::0;;::::1;::::0;;;;155881:14:::1;156085:15:::0;;;:6:::1;:15:::0;;;;;;156078:22;;;;::::1;::::0;;-1:-1:-1;;156078:22:0;;;155961:104;156142:29:::1;156092:7:::0;156142:20:::1;:29::i;:::-;156121:50:::0;-1:-1:-1;156182:22:0::1;147076:4;156208:28;-1:-1:-1::0;;;;;156208:28:0;;::::1;::::0;:15;::::1;:28;:::i;:::-;156207:42;;;;:::i;:::-;156260:20;:47:::0;;156182:67;;-1:-1:-1;156182:67:0;;156260:20:::1;::::0;:47:::1;::::0;156182:67;;-1:-1:-1;;;;;156260:47:0::1;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;156260:47:0::1;;;;;-1:-1:-1::0;;;;;156260:47:0::1;;;;;;156328:50;156340:7;156349;156358:19;;;;;;;;156372:1;156358:19;;;;;;156375:1;156358:19;;;;::::0;156328:11:::1;:50::i;:::-;156406:23;::::0;;;:14:::1;:23;::::0;;;;156399:30;;-1:-1:-1;;156399:30:0::1;::::0;;156450:14:::1;156421:7:::0;156450:5:::1;:14::i;:::-;156515:10;156500:26;::::0;;;:14:::1;:26;::::0;;;;:28;;-1:-1:-1;;156500:28:0;::::1;;::::0;;::::1;-1:-1:-1::0;;156500:28:0;;;::::1;;::::0;;156560:46:::1;::::0;-1:-1:-1;;;;;156560:13:0::1;:26;::::0;-1:-1:-1;;;;;156560:46:0;::::1;:26;:46::i;:::-;156632:37;::::0;-1:-1:-1;;;;;3501:47:1;;3483:66;;156653:7:0;;156641:10:::1;::::0;156632:37:::1;::::0;3471:2:1;3456:18;156632:37:0::1;;;;;;;155503:1174;;;;;;138765:20:::0;138159:1;139285:7;:22;139102:213;138765:20;155446:1231;:::o;165218:146::-;143571:13;:11;:13::i;:::-;-1:-1:-1;;;;;165288:23:0;::::1;165284:49;;165320:13;;-1:-1:-1::0;;;165320:13:0::1;;;;;;;;;;;165284:49;165340:8;:20:::0;;-1:-1:-1;;;;;;165340:20:0::1;-1:-1:-1::0;;;;;165340:20:0;;;::::1;::::0;;;::::1;::::0;;165218:146::o;108044:134::-;108131:39;108148:4;108154:2;108158:7;108131:39;;;;;;;;;;;;:16;:39::i;164180:586::-;138721:21;:19;:21::i;:::-;164265:14:::1;::::0;-1:-1:-1;;;164265:14:0;::::1;;;164257:48;;;::::0;-1:-1:-1;;;164257:48:0;;9927:2:1;164257:48:0::1;::::0;::::1;9909:21:1::0;9966:2;9946:18;;;9939:30;-1:-1:-1;;;9985:18:1;;;9978:51;10046:18;;164257:48:0::1;;;;;;;;;164340:10;164320:16;164328:7:::0;164320::::1;:16::i;:::-;-1:-1:-1::0;;;;;164320:30:0::1;;164316:58;;164359:15;;-1:-1:-1::0;;;164359:15:0::1;;;;;;;;;;;164316:58;164395:24;164422:15:::0;;;:6:::1;:15;::::0;;;;;;;164395:42;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;164395:42:0;;::::1;::::0;;;-1:-1:-1;;;164395:42:0;;::::1;;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;164395:42:0;::::1;::::0;;::::1;::::0;;;;164504:15;;;;;;;164497:22;;;-1:-1:-1;;164497:22:0;;;;164530:14:::1;164429:7:::0;164530:5:::1;:14::i;:::-;164595:10;164580:26;::::0;;;:14:::1;:26;::::0;;;;:28;;-1:-1:-1;;164580:28:0;::::1;;::::0;;::::1;-1:-1:-1::0;;164580:28:0;;;::::1;;::::0;;164640:46:::1;::::0;-1:-1:-1;;;;;164640:13:0::1;:26;::::0;-1:-1:-1;;;;;164640:46:0;::::1;:26;:46::i;:::-;164712;::::0;-1:-1:-1;;;;;3501:47:1;;3483:66;;164742:7:0;;164730:10:::1;::::0;164712:46:::1;::::0;3471:2:1;3456:18;164712:46:0::1;;;;;;;164246:520;;138765:20:::0;138159:1;139285:7;:22;139102: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;144360:103::-;143571:13;:11;:13::i;:::-;144425:30:::1;144452:1;144425:18;:30::i;:::-;144360:103::o:0;149707:425::-;149775:7;149822:15;;;:6;:15;;;;;;;;149795:42;;;;;;;;;-1:-1:-1;;;;;149795:42:0;;;;;-1:-1:-1;;;149795:42:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;149795:42:0;;;;;;;;;149859:15;149852:39;;149848:67;;-1:-1:-1;147028:4:0;;149707:425;-1:-1:-1;;149707:425:0:o;149848:67::-;149936:15;150020;149998:4;:12;;;:38;149987:49;;150114:8;150092:30;;150100:4;:10;;;-1:-1:-1;;;;;150092:19:0;:30;;;;:::i;:::-;150073:50;;147028:4;150073:50;:::i;:::-;150058:66;149707:425;-1:-1:-1;;;;149707:425:0:o;105704:95::-;105751:13;105784:7;105777:14;;;;;:::i;158945:199::-;159072:5;;;;;;159014:7;159059:19;;;:12;:19;;;;;;;;159034:44;;;;;;;;;;;;;;;-1:-1:-1;;;159034:44:0;;;;;;;;;;;;159072:5;159034:44;;;;;;;;;;;;-1:-1:-1;;;159034:44:0;;;;;;;;;159014:7;159104:31;159034:44;159125:9;159104;:31::i;:::-;159089:47;158945:199;-1:-1:-1;;;158945:199:0:o;106946:146::-;107032:52;16239:10;107065:8;107075;107032:18;:52::i;155208:226::-;155332:35;155353:4;155359:7;155332:20;:35::i;:::-;155379:47;155402:4;155408:2;155412:7;155421:4;155379:22;:47::i;:::-;155208:226;;;;:::o;160408:2544::-;138721:21;:19;:21::i;:::-;140763:19:::1;:17;:19::i;:::-;160545:8:::2;149475;149457:15;:26;149453:56;;;149492:17;;-1:-1:-1::0;;;149492:17:0::2;;;;;;;;;;;149453:56;160588:1:::3;160570:19:::0;::::3;160566:47;;;160598:15;;-1:-1:-1::0;;;160598:15:0::3;;;;;;;;;;;160566:47;160634:19;::::0;;160769:376:::3;160789:19:::0;;::::3;160769:376;;;160858:10;160834:20;160842:8:::0;;160851:1;160842:11;;::::3;;;;;:::i;:::-;;;;;;;160834:7;:20::i;:::-;-1:-1:-1::0;;;;;160834:34:0::3;;160830:62;;160877:15;;-1:-1:-1::0;;;160877:15:0::3;;;;;;;;;;;160830:62;160921:24;160948:6;:19;160955:8;;160964:1;160955:11;;;;;;;:::i;:::-;;::::0;;::::3;::::0;;;::::3;;160948:19:::0;;-1:-1:-1;160948:19:0;;::::3;::::0;;;;;;;;-1:-1:-1;160948:19:0;160921:46;;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;;;160921:46:0;;::::3;::::0;;;-1:-1:-1;;;160921:46:0;;::::3;;::::0;;::::3;::::0;;;;;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;;;;;-1:-1:-1;;;160921:46:0;::::3;::::0;;::::3;::::0;;;;;-1:-1:-1;160996:26:0::3;::::0;;::::3;:::i;:::-;;;161056:13;161041:28;;:4;:12;;;:28;;;161037:97;;;161106:4;:12;;;161090:28;;161037:97;-1:-1:-1::0;160810:3:0::3;;160769:376;;;-1:-1:-1::0;161204:24:0::3;161231:39;161254:15;161231:13:::0;:39:::3;:::i;:::-;161204:66:::0;-1:-1:-1;146870:8:0::3;161285:27;::::0;::::3;;161281:57;;;161321:17;;-1:-1:-1::0;;;161321:17:0::3;;;;;;;;;;;161281:57;161359:17;146870:8;161404:32;147028:4;146974;161404:32;:::i;:::-;-1:-1:-1::0;;;;;161380:57:0::3;161388:11;-1:-1:-1::0;;;;;161380:20:0::3;:57;;;;:::i;:::-;161379:69;;;;:::i;:::-;161359:89:::0;-1:-1:-1;;;;;;161463:29:0;::::3;161459:57;;;161501:15;;-1:-1:-1::0;;;161501:15:0::3;;;;;;;;;;;161459:57;161608:12;161606:14:::0;;161554:9;;161527:16:::3;::::0;161608:12:::3;::::0;161606:14:::3;::::0;-1:-1:-1;;;161606:14:0;::::3;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;161585:35;;;;161631:33;161641:10;161653;161631:9;:33::i;:::-;161739:9;161734:512;161754:19:::0;;::::3;161734:512;;;161795:15;161813:8;;161822:1;161813:11;;;;;;;:::i;:::-;;::::0;;::::3;::::0;;;::::3;;161839:27;161869:15:::0;;;:6:::3;:15:::0;;;;;;161839:45;;::::3;::::0;::::3;::::0;;;;-1:-1:-1;;;;;161839:45:0;;::::3;::::0;;-1:-1:-1;;;161839:45:0;;::::3;;::::0;;::::3;::::0;;;;::::3;::::0;::::3;::::0;;::::3;::::0;;;;;;-1:-1:-1;;;161839:45:0;;::::3;::::0;::::3;::::0;;;;161953:127;;;;::::3;::::0;;162009:14;;161953:127:::3;;::::0;;162049:15;;161953:127:::3;::::0;;::::3;::::0;162148:19;;;;::::3;::::0;;;;;;;;::::3;::::0;;;;161813:11;;-1:-1:-1;161839:45:0;161953:127;-1:-1:-1;162109:59:0::3;::::0;161813:11;;161953:127;;162109:11:::3;:59::i;:::-;162190:15;::::0;;;:6:::3;:15;::::0;;;;162183:22;;;;::::3;::::0;;-1:-1:-1;;162183:22:0;;;162220:14:::3;162197:7:::0;162220:5:::3;:14::i;:::-;-1:-1:-1::0;;;161775:3:0::3;;161734:512;;;-1:-1:-1::0;162317:110:0::3;::::0;;;;::::3;::::0;;::::3;::::0;;::::3;::::0;;::::3;::::0;::::3;;::::0;;::::3;::::0;;;;162472:19;;;;::::3;::::0;;;162286:28:::3;162472:19:::0;;;;;::::3;::::0;162317:110;162448:53:::3;::::0;162460:10;;162317:110;162448:11:::3;:53::i;:::-;162543:176;;;;;;;;162579:11;-1:-1:-1::0;;;;;162543:176:0::3;;;;;162699:8;-1:-1:-1::0;;;;;162543:176:0::3;;;;;162614:13;162543:176;;;;;;162661:15;162543:176;;;;::::0;162522:6:::3;:18;162529:10;162522:18;;;;;;;;;;;:197;;;;;;;;;;;;;-1:-1:-1::0;;;;;162522:197:0::3;;;;;-1:-1:-1::0;;;;;162522:197:0::3;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;162522:197:0::3;;;;;-1:-1:-1::0;;;;;162522:197:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;162827:8;;:15;;162792:14;:26;162807:10;-1:-1:-1::0;;;;;162792:26:0::3;-1:-1:-1::0;;;;;162792:26:0::3;;;;;;;;;;;;;;;;;;;;;;:51;162846:1;162792:55;162757:14;:26;162772:10;-1:-1:-1::0;;;;;162757:26:0::3;-1:-1:-1::0;;;;;162757:26:0::3;;;;;;;;;;;;;:91;;;;;;;;;;;;;;;;;;162905:10;162893;-1:-1:-1::0;;;;;162885:59:0::3;;162917:11;162930:13;162885:59;;;;;;-1:-1:-1::0;;;;;11140:47:1;;;;11122:66;;11236:10;11224:23;11219:2;11204:18;;11197:51;11110:2;11095:18;;10950:304;162885:59:0::3;;;;;;;;160555:2397;;;;;;;140793:1:::2;138765:20:::0;138159:1;139285:7;:22;139102:213;164000:172;143571:13;:11;:13::i;:::-;164061:14:::1;:21:::0;;-1:-1:-1;;;;164061:21:0::1;-1:-1:-1::0;;;164061:21:0::1;::::0;;164093:8:::1;:6;:8::i;:::-;164138:25;::::0;164117:47:::1;::::0;-1:-1:-1;;;;;164138:25:0;;::::1;1488:51:1::0;;164117:47:0::1;::::0;1476:2:1;1461:18;164117:47:0::1;;;;;;;;164000:172::o:0;165368:495::-;165496:1;109103:16;;;:7;:16;;;;;;165441:13;;-1:-1:-1;;;;;109103:16:0;165463:60;;165507:16;;-1:-1:-1;;;165507:16:0;;;;;;;;;;;165463:60;165534:8;;-1:-1:-1;;;;;165534:8:0;165530:52;;165565:17;;-1:-1:-1;;;165565:17:0;;;;;;;;;;;165530:52;165675:8;;165705:53;;;;;4282:25:1;;;165640:12:0;;;;-1:-1:-1;;;;;165675:8:0;;;;4255:18:1;;165705:53:0;;;-1:-1:-1;;165705:53:0;;;;;;;;;;;;;;-1:-1:-1;;;;;165705:53:0;-1:-1:-1;;;165705:53:0;;;165675:90;;;165705:53;165675:90;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;165639:126;;;;165780:7;165772:41;;;;-1:-1:-1;;;165772:41:0;;11767:2:1;165772:41:0;;;11749:21:1;11806:2;11786:18;;;11779:30;-1:-1:-1;;;11825:18:1;;;11818:51;11886:18;;165772:41:0;11565:345:1;165772:41:0;165844:4;165833:26;;;;;;;;;;;;:::i;162960:490::-;163041:7;163080:23;;;:14;:23;;;;;;;;163118:14;;;163114:28;;163141:1;163134:8;;;;;163114:28;163155:22;163180:25;;;:16;:25;;;;;;;;:36;;;;;;;;;;;;;163155:61;;;;;;;;;;;;;;;-1:-1:-1;;;163155:61:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;163155:61:0;;;;;;;;;;163278:24;;:9;:24;:::i;:::-;163270:33;;163245:9;:15;;;:59;;;;:::i;:::-;163227:77;;:9;;:77;;;;;:::i;:::-;;;;;;;;163319:14;;163336:1;163319:18;;;163315:69;;-1:-1:-1;163315:69:0;;163371:1;163354:18;;163315:69;163425:14;-1:-1:-1;;;;;163409:32:0;;162960:490;-1:-1:-1;;;;162960:490:0:o;163458:506::-;163637:15;;163542:7;;;;163637:15;-1:-1:-1;;;163637:15:0;;;;;163622:30;;;;:78;;163688:12;163622:78;;;163670:15;;163655:30;;-1:-1:-1;;;163670:15:0;;;;163655:12;:30;:::i;:::-;163601:99;-1:-1:-1;163764:17:0;146870:8;163804:32;147028:4;146974;163804:32;:::i;:::-;-1:-1:-1;;;;;163785:52:0;163793:6;-1:-1:-1;;;;;163785:15:0;:52;;;;:::i;:::-;163784:64;;;;:::i;:::-;163764:84;-1:-1:-1;163764:84:0;163930:28;;;;-1:-1:-1;;;;;163930:14:0;;:28;:::i;:::-;163911:48;;147028:4;163911:48;:::i;:::-;163896:64;163458:506;-1:-1:-1;;;;;;163458:506:0:o;156685:2252::-;156895:15;138721:21;:19;:21::i;:::-;140763:19:::1;:17;:19::i;:::-;156876:8:::2;149475;149457:15;:26;149453:56;;;149492:17;;-1:-1:-1::0;;;149492:17:0::2;;;;;;;;;;;149453:56;156927:6:::3;-1:-1:-1::0;;;;;156927:11:0::3;156937:1;156927:11:::0;156923:39:::3;;156947:15;;-1:-1:-1::0;;;156947:15:0::3;;;;;;;;;;;156923:39;156977:17;::::0;::::3;::::0;;:43:::3;;-1:-1:-1::0;146870:8:0::3;156998:22;::::0;::::3;;156977:43;156973:73;;;157029:17;;-1:-1:-1::0;;;157029:17:0::3;;;;;;;;;;;156973:73;157076:10;157061:26;::::0;;;:14:::3;:26;::::0;;;;;147131:3:::3;157061:48;:26:::0;;::::3;:48;157057:78;;157118:17;;-1:-1:-1::0;;;157118:17:0::3;;;;;;;;;;;157057:78;157156:17;157176:38;157202:12:::0;157183:15:::3;157176:38;:::i;:::-;157156:58:::0;-1:-1:-1;157278:17:0::3;146870:8;157318:32;147028:4;146974;157318:32;:::i;:::-;-1:-1:-1::0;;;;;157299:52:0::3;157307:6;-1:-1:-1::0;;;;;157299:15:0::3;:52;;;;:::i;:::-;157298:64;;;;:::i;:::-;157278:84:::0;-1:-1:-1;;;;;;157377:29:0;::::3;157373:57;;;157415:15;;-1:-1:-1::0;;;157415:15:0::3;;;;;;;;;;;157373:57;157465:9:::0;157441:13:::3;157582:29;;::::0;::::3;-1:-1:-1::0;;;;;157582:14:0;::::3;:29;:::i;:::-;157563:49;::::0;147028:4:::3;157563:49;:::i;:::-;157534:79;;157641:13;-1:-1:-1::0;;;;;157628:26:0::3;:10;-1:-1:-1::0;;;;;157628:26:0::3;;157624:57;;;157663:18;;-1:-1:-1::0;;;157663:18:0::3;;;;;;;;;;;157624:57;157728:28;157759:102;;;;;;;;157811:6;157759:102;;;;;;157839:10;157759:102;;;;::::0;157728:133:::3;;157928:44;157940:1;157943:19;;;;;;;;157957:1;157943:19;;;;;;157960:1;157943:19;;;;::::0;157964:7:::3;157928:11;:44::i;:::-;158051:38;::::0;-1:-1:-1;;;158051:38:0;;158083:4:::3;158051:38;::::0;::::3;1488:51:1::0;158027:21:0::3;::::0;158051:13:::3;-1:-1:-1::0;;;;;158051:23:0::3;::::0;::::3;::::0;1461:18:1;;158051:38:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;158027:62;;158100:65;158131:10;158151:4;158158:6;-1:-1:-1::0;;;;;158100:65:0::3;:13;-1:-1:-1::0;;;;;158100:30:0::3;;;:65;;;;;;:::i;:::-;158222:22;-1:-1:-1::0;;;;;158222:22:0;::::3;:13:::0;:22:::3;:::i;:::-;158180:38;::::0;-1:-1:-1;;;158180:38:0;;158212:4:::3;158180:38;::::0;::::3;1488:51:1::0;158180:13:0::3;-1:-1:-1::0;;;;;158180:23:0::3;::::0;::::3;::::0;1461:18:1;;158180:38:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:64;158176:107;;158267:16;;-1:-1:-1::0;;;158267:16:0::3;;;;;;;;;;;158176:107;158329:12;:14:::0;;::::3;;-1:-1:-1::0;;;158329:14:0;;::::3;::::0;::::3;::::0;;::::3;::::0;;::::3;;-1:-1:-1::0;;;;158329:14:0;;::::3;::::0;;;::::3;::::0;;;158373:10:::3;-1:-1:-1::0;158358:26:0;;;:14:::3;:26;::::0;;;;:28;;::::3;::::0;;::::3;::::0;;::::3;::::0;;::::3;-1:-1:-1::0;;158358:28:0;;::::3;::::0;;;::::3;::::0;;;158329:14;-1:-1:-1;158408:30:0::3;::::0;158329:14;158408:9:::3;:30::i;:::-;158467:165;;;;;;;;158503:6;-1:-1:-1::0;;;;;158467:165:0::3;;;;;158615:5;-1:-1:-1::0;;;;;158467:165:0::3;;;;;158533:10;158467:165;;;;;;158577:15;158467:165;;;;::::0;158449:6:::3;:15;158456:7;158449:15;;;;;;;;;;;:183;;;;;;;;;;;;;-1:-1:-1::0;;;;;158449:183:0::3;;;;;-1:-1:-1::0;;;;;158449:183:0::3;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;158449:183:0::3;;;;;-1:-1:-1::0;;;;;158449:183:0::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158643:30;147076:4;-1:-1:-1::0;;;;;158676:42:0::3;158695:10;-1:-1:-1::0;;;;;158677:28:0::3;158685:6;-1:-1:-1::0;;;;;158677:15:0::3;:28;;;;:::i;:::-;158676:42;;;;:::i;:::-;158643:75:::0;-1:-1:-1;;;;;;158733:42:0;::::3;158729:70;;;158784:15;;-1:-1:-1::0;;;158784:15:0::3;;;;;;;;;;;158729:70;158810:20;:55:::0;;158842:22;;158810:20;::::3;::::0;:55:::3;::::0;158842:22;;-1:-1:-1;;;;;158810:55:0::3;;:::i;:::-;;;;;;;;-1:-1:-1::0;;;;;158810:55:0::3;;;;;-1:-1:-1::0;;;;;158810:55:0::3;;;;;;158901:7;158889:10;-1:-1:-1::0;;;;;158881:48:0::3;;158910:6;158918:10;158881:48;;;;;;-1:-1:-1::0;;;;;11140:47:1;;;;11122:66;;11236:10;11224:23;11219:2;11204:18;;11197:51;11110:2;11095:18;;10950:304;158881:48:0::3;;;;;;;;156912:2025;;;;;;;140793:1:::2;138765:20:::0;138159:1;139285:7;:22;139102:213;107163:155;-1:-1:-1;;;;;107275:25:0;;;107251:4;107275:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;107163:155::o;144618:220::-;143571:13;:11;:13::i;:::-;-1:-1:-1;;;;;144703:22:0;::::1;144699:93;;144749:31;::::0;-1:-1:-1;;;144749:31:0;;144777:1:::1;144749:31;::::0;::::1;1488:51:1::0;1461:18;;144749:31:0::1;1342:203:1::0;144699:93:0::1;144802:28;144821:8;144802:18;:28::i;164774:68::-:0;143571:13;:11;:13::i;:::-;164824: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;;;;;4282:25:1;;;4255:18;;119941:31:0;4136:177:1;117999:122:0;118080:33;118089:2;118093:7;118102:4;118108;118080:8;:33::i;154739:261::-;-1:-1:-1;;;;;154849:18:0;;;;;;:58;;-1:-1:-1;154879:13:0;-1:-1:-1;;;;;154871:36:0;;;154849:58;154845:138;;;154943:28;;-1:-1:-1;;;154943:28:0;;;;;4282:25:1;;;154943:13:0;-1:-1:-1;;;;;154943:19:0;;;;4255:18:1;;154943: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;;;;;13687:32:1;;;107904:50:0;;;13669:51:1;13736:18;;;13729:34;;;13799:32;;13779:18;;;13772:60;13642:18;;107904:50:0;13467:371:1;138801:293:0;138203:1;138935:7;;:19;138927:63;;;;-1:-1:-1;;;138927:63:0;;14045:2:1;138927:63:0;;;14027:21:1;14084:2;14064:18;;;14057:30;14123:33;14103:18;;;14096:61;14174:18;;138927:63:0;13843:355:1;138927:63:0;138203:1;139068:7;:18;138801:293::o;150140:363::-;150296:19;:17;:19::i;:::-;150340:12;;150336:160;;150369:115;150404:7;150431:9;150460;150369:16;:115::i;114945:232::-;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;;;;;4282:25:1;;;4255:18;;115127:31:0;4136:177:1;128181:162:0;128291:43;;-1:-1:-1;;;;;14395:32:1;;;128291:43:0;;;14377:51:1;14444:18;;;14437:34;;;128264:71:0;;128284:5;;128306:14;;;;;14350:18:1;;128291:43:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;128291:43:0;;;;;;;;;;;128264:19;:71::i;143850:166::-;143758:6;;-1:-1:-1;;;;;143758:6:0;;;;;16239:10;143910:23;143906:103;;143957:40;;-1:-1:-1;;;143957:40:0;;16239:10;143957:40;;;1488:51:1;1461:18;;143957:40:0;1342:203:1;144998:191:0;145091:6;;;-1:-1:-1;;;;;145108:17:0;;;145091:6;145108:17;;;-1:-1:-1;;;;;;145108:17:0;;;;;;145141:40;;145091:6;;;;;;;;145141:40;;145072:16;;145141:40;145061:128;144998:191;:::o;159152:801::-;159224:7;159244:22;159269:5;159244:30;;159285:9;146916;;159298;:12;;;:19;;;;:::i;:::-;159297:28;;;;:::i;:::-;159285:40;-1:-1:-1;159351:9:0;159346:460;159370:3;159366:1;:7;159346:460;;;159395:10;146916:9;159395:10;;:::i;:::-;;-1:-1:-1;159420:13:0;159456:6;;;;;;;;159452:119;;;159488:1;159483:6;;159452:119;;;-1:-1:-1;159539:16:0;;;;;;;:12;:16;;;;;;;;159452:119;159641:12;;;;159636:17;;:2;:17;:::i;:::-;159628:26;;159603:9;:15;;;:52;;;;:::i;:::-;159585:70;;:9;;:70;;;;;:::i;:::-;;;;;-1:-1:-1;159674:7:0;;;;;;;;159670:53;;159702:5;;;159670:53;159756:6;159737:9;:15;;:25;;;;;;;:::i;:::-;;;;;-1:-1:-1;;159777:17:0;;;:12;;;:17;159375:3;;159346:460;;;;159839:1;159822:9;:14;;;:18;;;159818:69;;;159874:1;159857:18;;159818:69;-1:-1:-1;159928:14:0;-1:-1:-1;;;;;159912:32:0;;159152:801;-1:-1:-1;;;159152: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;141317:108::-;141229:7;;;;141387:9;141379:38;;;;-1:-1:-1;;;141379:38:0;;15366:2:1;141379:38:0;;;15348:21:1;15405:2;15385:18;;;15378:30;-1:-1:-1;;;15424:18:1;;;15417:46;15480:18;;141379:38:0;15164:340:1;114067:102:0;114135:26;114145:2;114149:7;114135:26;;;;;;;;;;;;:9;:26::i;141754:118::-;140763:19;:17;:19::i;:::-;141814:7:::1;:14:::0;;-1:-1:-1;;141814:14:0::1;141824:4;141814:14;::::0;;141844:20:::1;141851:12;16239:10:::0;;16159:98;141851:12:::1;141844:20;::::0;-1:-1:-1;;;;;1506:32:1;;;1488:51;;1476:2;1461:18;141844:20:0::1;1342:203:1::0;128588:190:0;128716:53;;-1:-1:-1;;;;;15729:32:1;;;128716:53:0;;;15711:51:1;15798:32;;;15778:18;;;15771:60;15847:18;;;15840:34;;;128689:81:0;;128709:5;;128731:18;;;;;15684::1;;128716:53:0;15509:371:1;142013:120:0;141022:16;:14;:16::i;:::-;142072:7:::1;:15:::0;;-1:-1:-1;;142072:15:0::1;::::0;;142103:22:::1;16239:10:::0;142112: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;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;150511:946::-;150576:5;;;;150592:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;150592:22:0;150639:10;;;;150635:289;;150678:12;:24;150691:10;150700:1;150691:6;:10;:::i;:::-;150678:24;;;;;;;;;;;;;;;;;;-1:-1:-1;150678:24:0;150666:36;;;;;;;;;;;;;;;-1:-1:-1;;;150666:36:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;150666:36:0;;;;;;;;;-1:-1:-1;150635:289:0;;;-1:-1:-1;150747:165:0;;;;;;;;-1:-1:-1;150747:165:0;;;;;;;;150836:15;150747:165;;;;;;;;;150883:12;150747:165;;;;;;;150635:289;150960:12;;;;150936:21;151030:40;;;;151037:15;151030:40;;;;151026:198;;;151198:12;;;;151180:30;;;;:15;:30;:::i;:::-;151137:13;;;;151122:28;;;;:12;:28;:::i;:::-;151109:42;;147076:4;151109:42;:::i;:::-;151108:103;;;;:::i;:::-;151087:125;;151026:198;151287:135;151327:9;151351:14;151380:10;151405:6;151287:25;:135::i;:::-;-1:-1:-1;;151435:5:0;:14;;-1:-1:-1;;151435:14:0;;;;;;;;;;;;;-1:-1:-1;;150511:946:0:o;152749:1160::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;153003:15:0;152980:39;;:9;:13;;;:39;;;:63;;;;;153042:1;153023:9;:16;;;:20;;;152980:63;152976:257;;;153073:16;;:27;;146870:8;;153073:27;:::i;:::-;153060:40;;:10;;;;:40;;;;153180:13;;;:39;;153203:15;;153180:39;:::i;:::-;153172:48;;153127:4;:10;;;:94;;;;:::i;:::-;153115:106;;;;152976:257;153280:15;153257:39;;:9;:13;;;:39;;;:63;;;;;153319:1;153300:9;:16;;;:20;;;153257:63;153253:257;;;153350:16;;:27;;146870:8;;153350:27;:::i;:::-;153337:40;;:10;;;;:40;;;;153457:13;;;:39;;153480:15;;153457:39;:::i;:::-;153449:48;;153404:4;:10;;;:94;;;;:::i;:::-;153392:106;;;;153253:257;153522:134;153562:9;153586;153610:4;:10;;;153635:4;:10;;;153522:25;:134::i;:::-;153669:16;153688:23;;;:14;:23;;;;;;:27;;:23;;;:27;:::i;:::-;153726:23;;;;:14;:23;;;;;;;;:35;;;;;;-1:-1:-1;;153726:35:0;;;;;;;;153789:15;153772:33;;:7;;;:33;;;153834:12;153816:31;;:8;;;:31;;;153858:25;;;:16;:25;;;;;:36;;;;;;;;:43;;;;;;;-1:-1:-1;;;;;153858:43:0;;;-1:-1:-1;;;153858:43:0;;;;;;;;;;153726:35;153858:43;;;;;;;;;;-1:-1:-1;;;153858:43:0;-1:-1:-1;;153858:43:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;;152749:1160:0:o;134774:738::-;134855:18;134884:19;135024:4;135021:1;135014:4;135008:11;135001:4;134995;134991:15;134988:1;134981:5;134974;134969:60;135083:7;135073:180;;135128:4;135122:11;135174:16;135171:1;135166:3;135151:40;135221:16;135216:3;135209:29;135073:180;-1:-1:-1;;135332:1:0;135326:8;135281:16;;-1:-1:-1;135361:15:0;;:68;;135413:11;135428:1;135413:16;;135361:68;;;-1:-1:-1;;;;;135379:26:0;;;:31;135361:68;135357:148;;;135453:40;;-1:-1:-1;;;135453:40:0;;-1:-1:-1;;;;;1506:32:1;;135453:40:0;;;1488:51:1;1461:18;;135453: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;141502:108::-;141229:7;;;;141561:41;;;;-1:-1:-1;;;141561:41:0;;17274:2:1;141561:41:0;;;17256:21:1;17313:2;17293:18;;;17286:30;-1:-1:-1;;;17332:18:1;;;17325:50;17392:18;;141561:41:0;17072:344:1;110416:376:0;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;;;;;4282:25:1;;;4255:18;;110635:31:0;4136:177:1;110584:190:0;110714:44;;-1:-1:-1;;;110714:44:0;;-1:-1:-1;;;;;14395:32:1;;110714:44:0;;;14377:51:1;14444:18;;;14437:34;;;14350:18;;110714:44:0;14203:274:1;151465:1276:0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;151700:9:0;151668:29;146916:9;151733:21;146916:9;151733:14;:21;:::i;:::-;151732:30;;;;:::i;:::-;151720:42;-1:-1:-1;151788:9:0;151783:914;151807:3;151803:1;:7;151783:914;;;151832:10;146916:9;151832:10;;:::i;:::-;;-1:-1:-1;151857:13:0;151907:28;151919:15;151907:28;;;;;;151903:163;;;151968:15;151956:28;;151903:163;;;-1:-1:-1;152034:16:0;;;;;;;:12;:16;;;;;;;;151903:163;152145:19;152150:14;152145:2;:19;:::i;:::-;152137:28;;152112:9;:15;;;:54;;;;:::i;:::-;152094:72;;:9;;:72;;;;;:::i;:::-;;;;;-1:-1:-1;152181:15:0;;;:25;;152200:6;;152181:15;:25;;152200:6;;152181:25;:::i;:::-;;;;;-1:-1:-1;152221:17:0;;;:12;;;;:17;;;;152356:19;;;147076:4;;152351:24;;152236:2;152351:24;:::i;:::-;152328:48;;;;-1:-1:-1;;;;;152328:19:0;;:48;:::i;:::-;152327:62;;;;:::i;:::-;152276:16;:20;;;:113;;;;;;:::i;:::-;152253:137;;;;:13;;;:137;152436:15;152423:29;;;;;;152419:219;;-1:-1:-1;152473:36:0;152496:12;152473:36;:13;;;:36;152528:5;;152419:219;152613:9;152574:12;:36;152607:1;152587:10;:6;152596:1;152587:10;:::i;:::-;:22;;;;:::i;:::-;152574:36;;;;;;;;;;;;;;;;;;-1:-1:-1;152574:36:0;:48;;;;;;-1:-1:-1;;;;;152574:48:0;;;-1:-1:-1;;;152574:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;152574:48:0;-1:-1:-1;;152574:48:0;;;;;;;;;;;;;;;;;-1:-1:-1;152683:2:0;;-1:-1:-1;152683:2:0;;151812:3;;151783:914;;;-1:-1:-1;152724:9:0;;151465:1276;-1:-1:-1;;;;;;151465:1276:0:o;153917:814::-;154140:15;154117:39;;:9;:13;;;:39;;;154113:314;;;154205:13;;;;;154192:27;;154173:16;154192:27;;;:12;:27;;;;;;;;;154234:21;154247:8;154192:27;154234:21;:::i;:::-;;;154291:9;:13;;;154274:30;;:9;:13;;;:30;;;154270:92;;154325:21;154338:8;154325:21;;:::i;:::-;;;154270:92;154389:13;;;;;154376:27;;;;;;:12;:27;;;;;;:39;;-1:-1:-1;;;;;;154376:39:0;-1:-1:-1;;;;;154376:39:0;;;;;;;;;;154113:314;154466:15;154443:39;;:9;:13;;;:39;;;154439:285;;;154519:9;:13;;;154503:29;;:9;:13;;;:29;;;154499:214;;;154585:13;;;;;154572:27;;154553:16;154572:27;;;:12;:27;;;;;;;;;154618:21;154631:8;154572:27;154618:21;:::i;:::-;154671:13;;;;;154658:27;;;;;;:12;:27;;;;;;:39;;-1:-1:-1;;;;;154658:39:0;;;-1:-1:-1;;;;;;154658:39:0;;;;;;;;;-1:-1:-1;153917:814:0;;;;:::o;113369:335::-;-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:163::-;2100:20;;2160:10;2149:22;;2139:33;;2129:61;;2186:1;2183;2176:12;2201:298;2268:6;2276;2329:2;2317:9;2308:7;2304:23;2300:32;2297:52;;;2345:1;2342;2335:12;2297:52;2390:23;;;-1:-1:-1;2456:37:1;2489:2;2474:18;;2456:37;:::i;:::-;2446:47;;2201:298;;;;;:::o;2958:374::-;3035:6;3043;3051;3104:2;3092:9;3083:7;3079:23;3075:32;3072:52;;;3120:1;3117;3110:12;3072:52;3143:29;3162:9;3143:29;:::i;:::-;3133:39;;3191:38;3225:2;3214:9;3210:18;3191:38;:::i;:::-;2958:374;;3181:48;;-1:-1:-1;;;3298:2:1;3283:18;;;;3270:32;;2958:374::o;3560:186::-;3619:6;3672:2;3660:9;3651:7;3647:23;3643:32;3640:52;;;3688:1;3685;3678:12;3640:52;3711:29;3730:9;3711:29;:::i;3751:184::-;3809:6;3862:2;3850:9;3841:7;3837:23;3833:32;3830:52;;;3878:1;3875;3868:12;3830:52;3901:28;3919:9;3901:28;:::i;4704:347::-;4769:6;4777;4830:2;4818:9;4809:7;4805:23;4801:32;4798:52;;;4846:1;4843;4836:12;4798:52;4869:29;4888:9;4869:29;:::i;:::-;4859:39;;4948:2;4937:9;4933:18;4920:32;4995:5;4988:13;4981:21;4974:5;4971:32;4961:60;;5017:1;5014;5007:12;4961:60;5040:5;5030:15;;;4704:347;;;;;:::o;5056:127::-;5117:10;5112:3;5108:20;5105:1;5098:31;5148:4;5145:1;5138:15;5172:4;5169:1;5162:15;5188:275;5259:2;5253:9;5324:2;5305:13;;-1:-1:-1;;5301:27:1;5289:40;;5359:18;5344:34;;5380:22;;;5341:62;5338:88;;;5406:18;;:::i;:::-;5442:2;5435:22;5188:275;;-1:-1:-1;5188:275:1:o;5468:186::-;5516:4;5549:18;5541:6;5538:30;5535:56;;;5571:18;;:::i;:::-;-1:-1:-1;5637:2:1;5616:15;-1:-1:-1;;5612:29:1;5643:4;5608:40;;5468:186::o;5659:958::-;5754:6;5762;5770;5778;5831:3;5819:9;5810:7;5806:23;5802:33;5799:53;;;5848:1;5845;5838:12;5799:53;5871:29;5890:9;5871:29;:::i;:::-;5861:39;;5919:38;5953:2;5942:9;5938:18;5919:38;:::i;:::-;5909:48;-1:-1:-1;6026:2:1;6011:18;;5998:32;;-1:-1:-1;6105:2:1;6090:18;;6077:32;6132:18;6121:30;;6118:50;;;6164:1;6161;6154:12;6118:50;6187:22;;6240:4;6232:13;;6228:27;-1:-1:-1;6218:55:1;;6269:1;6266;6259:12;6218:55;6309:2;6296:16;6334:52;6350:35;6378:6;6350:35;:::i;:::-;6334:52;:::i;:::-;6409:6;6402:5;6395:21;6457:7;6452:2;6443:6;6439:2;6435:15;6431:24;6428:37;6425:57;;;6478:1;6475;6468:12;6425:57;6533:6;6528:2;6524;6520:11;6515:2;6508:5;6504:14;6491:49;6585:1;6580:2;6571:6;6564:5;6560:18;6556:27;6549:38;6606:5;6596:15;;;;;5659:958;;;;;;;:::o;6622:730::-;6717:6;6725;6733;6786:2;6774:9;6765:7;6761:23;6757:32;6754:52;;;6802:1;6799;6792:12;6754:52;6842:9;6829:23;6875:18;6867:6;6864:30;6861:50;;;6907:1;6904;6897:12;6861:50;6930:22;;6983:4;6975:13;;6971:27;-1:-1:-1;6961:55:1;;7012:1;7009;7002:12;6961:55;7052:2;7039:16;7078:18;7070:6;7067:30;7064:50;;;7110:1;7107;7100:12;7064:50;7165:7;7158:4;7148:6;7145:1;7141:14;7137:2;7133:23;7129:34;7126:47;7123:67;;;7186:1;7183;7176:12;7123:67;7217:4;7209:13;;;;7241:6;;-1:-1:-1;7301:20:1;;7288:34;;6622:730;-1:-1:-1;;;6622:730:1:o;7357:188::-;7425:20;;-1:-1:-1;;;;;7474:46:1;;7464:57;;7454:85;;7535:1;7532;7525:12;7550:258;7617:6;7625;7678:2;7666:9;7657:7;7653:23;7649:32;7646:52;;;7694:1;7691;7684:12;7646:52;7717:29;7736:9;7717:29;:::i;:::-;7707:39;;7765:37;7798:2;7787:9;7783:18;7765:37;:::i;7813:447::-;7898:6;7906;7914;7922;7975:3;7963:9;7954:7;7950:23;7946:33;7943:53;;;7992:1;7989;7982:12;7943:53;8015:29;8034:9;8015:29;:::i;:::-;8005:39;;8063:37;8096:2;8085:9;8081:18;8063:37;:::i;:::-;8053:47;-1:-1:-1;8169:2:1;8154:18;;8141:32;;-1:-1:-1;8216:38:1;8250:2;8235:18;;8216:38;:::i;:::-;8206:48;;7813:447;;;;;;;:::o;8265:260::-;8333:6;8341;8394:2;8382:9;8373:7;8369:23;8365:32;8362:52;;;8410:1;8407;8400:12;8362:52;8433:29;8452:9;8433:29;:::i;:::-;8423:39;;8481:38;8515:2;8504:9;8500:18;8481:38;:::i;8530:380::-;8609:1;8605:12;;;;8652;;;8673:61;;8727:4;8719:6;8715:17;8705:27;;8673:61;8780:2;8772:6;8769:14;8749:18;8746:38;8743:161;;8826:10;8821:3;8817:20;8814:1;8807:31;8861:4;8858:1;8851:15;8889:4;8886:1;8879:15;8743:161;;8530:380;;;:::o;8915:127::-;8976:10;8971:3;8967:20;8964:1;8957:31;9007:4;9004:1;8997:15;9031:4;9028:1;9021:15;9047:168;9120:9;;;9151;;9168:15;;;9162:22;;9148:37;9138:71;;9189:18;;:::i;9220:127::-;9281:10;9276:3;9272:20;9269:1;9262:31;9312:4;9309:1;9302:15;9336:4;9333:1;9326:15;9352:120;9392:1;9418;9408:35;;9423:18;;:::i;:::-;-1:-1:-1;9457:9:1;;9352:120::o;9477:243::-;-1:-1:-1;;;;;9592:42:1;;;9548;;;9544:91;;9647:44;;9644:70;;;9694:18;;:::i;10075:125::-;10140:9;;;10161:10;;;10158:36;;;10174:18;;:::i;10205:127::-;10266:10;10261:3;10257:20;10254:1;10247:31;10297:4;10294:1;10287:15;10321:4;10318:1;10311:15;10337:240;-1:-1:-1;;;;;10406:42:1;;;10450;;;10402:91;;10505:43;;10502:69;;;10551:18;;:::i;10582:170::-;10679:10;10672:18;;;10652;;;10648:43;;10703:20;;10700:46;;;10726:18;;:::i;10757:188::-;10795:3;10839:10;10832:5;10828:22;10874:10;10865:7;10862:23;10859:49;;10888:18;;:::i;:::-;10937:1;10924:15;;10757:188;-1:-1:-1;;10757:188:1:o;11259:301::-;11388:3;11426:6;11420:13;11472:6;11465:4;11457:6;11453:17;11448:3;11442:37;11534:1;11498:16;;11523:13;;;-1:-1:-1;11498:16:1;11259:301;-1:-1:-1;11259:301:1:o;11915:686::-;11995:6;12048:2;12036:9;12027:7;12023:23;12019:32;12016:52;;;12064:1;12061;12054:12;12016:52;12097:9;12091:16;12130:18;12122:6;12119:30;12116:50;;;12162:1;12159;12152:12;12116:50;12185:22;;12238:4;12230:13;;12226:27;-1:-1:-1;12216:55:1;;12267:1;12264;12257:12;12216:55;12300:2;12294:9;12325:52;12341:35;12369:6;12341:35;:::i;12325:52::-;12400:6;12393:5;12386:21;12448:7;12443:2;12434:6;12430:2;12426:15;12422:24;12419:37;12416:57;;;12469:1;12466;12459:12;12416:57;12517:6;12512:2;12508;12504:11;12499:2;12492:5;12488:14;12482:42;12569:1;12544:18;;;12564:2;12540:27;12533:38;;;;12548:5;11915:686;-1:-1:-1;;;;11915:686:1:o;12606:241::-;12645:7;12724:1;12720:2;12709:17;12705:1;12701:2;12690:17;12686:41;12762:11;12758:2;12747:27;12736:38;;12805:11;12796:7;12793:24;12783:58;;12821:18;;:::i;:::-;12783:58;12606:241;;;;:::o;12852:249::-;12952:2;12941:17;;;12922;;;;12918:41;-1:-1:-1;;;;;;12974:50:1;;-1:-1:-1;;;;;13026:45:1;;12971:101;12968:127;;;13075:18;;:::i;13106:167::-;13201:10;13174:18;;;13194;;;13170:43;;13225:19;;13222:45;;;13247:18;;:::i;13278:184::-;13348:6;13401:2;13389:9;13380:7;13376:23;13372:32;13369:52;;;13417:1;13414;13407:12;13369:52;-1:-1:-1;13440:16:1;;13278:184;-1:-1:-1;13278:184:1:o;14482:178::-;14521:1;14555:10;14552:1;14548:18;14585:3;14575:37;;14592:18;;:::i;:::-;14650:3;14637:10;14634:1;14630:18;14626:28;14621:33;;;14482:178;;;;:::o;14665:244::-;14776:10;14749:18;;;14769;;;14745:43;14808:28;;;;14855:24;;;14845:58;;14883:18;;:::i;14914:245::-;15012:2;14982:17;;;15001;;;;14978:41;-1:-1:-1;;;;;15034:44:1;;-1:-1:-1;;;;;;15080:49:1;;15031:99;15028:125;;;15133:18;;:::i;15885:128::-;15952:9;;;15973:11;;;15970:37;;;15987:18;;:::i;16018:305::-;16057:1;16099;16095:2;16084:17;16136:1;16132:2;16121:17;16157:3;16147:37;;16164:18;;:::i;:::-;-1:-1:-1;;;;;;16200:48:1;;-1:-1:-1;;16250:15:1;;16196:70;16193:96;;;16269:18;;:::i;:::-;16303:14;;;16018:305;-1:-1:-1;;;16018:305:1:o;16328:485::-;-1:-1:-1;;;;;16559:32:1;;;16541:51;;16628:32;;16623:2;16608:18;;16601:60;16692:2;16677:18;;16670:34;;;16740:3;16735:2;16720:18;;16713:31;;;-1:-1:-1;;16761:46:1;;16787:19;;16779:6;16761:46;:::i;16818:249::-;16887:6;16940:2;16928:9;16919:7;16915:23;16911:32;16908:52;;;16956:1;16953;16946:12;16908:52;16988:9;16982:16;17007:30;17031:5;17007:30;:::i
Swarm Source
ipfs://fb0bea65dd5a26c1473f6c42b5f1881f29b1295416b1db4abcf930bc5a3cc817
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.