More Info
Private Name Tags
ContractCreator
TokenTracker
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
ProjectNineNFT
Compiler Version
v0.8.26+commit.8a97fa7a
Contract Source Code (Solidity)
/** *Submitted for verification at apescan.io on 2025-02-20 */ /** * _ _ _ _ _ _ _ _ * /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ / /\ * / \ \ / \ \ / \ \ \ \ \ / \ \ / \ \ \_\ \ / / \ * / /\ \ \ / /\ \ \ / /\ \ \ /\ \_\ / /\ \ \ / /\ \ \ /\__ \ / / /\ \ * / / /\ \_\ / / /\ \_\ / / /\ \ \ / /\/_// / /\ \_\ / / /\ \ \ / /_ \ \ /_/ /\ \ \ * / / /_/ / // / /_/ / / / / / \ \_\ _ / / / / /_/_ \/_/ / / / \ \_\ / / /\ \ \ \ \ \_\ \ \ * / / /__\/ // / /__\/ / / / / / / //\ \ / / / / /____/\ / / / \/_/ / / / \/_/ \ \/__\ \ \ * / / /_____// / /_____/ / / / / / / \ \_\ / / / / /\____\/ / / / / / / \_____\ \ \ * / / / / / /\ \ \ / / /___/ / / / / /_/ / / / / /______ / / /________ / / / \ \ \ * / / / / / / \ \ \/ / /____\/ / / / /__\/ / / / /_______\/ / /_________\/_/ / \ \ \ * \/_/ \/_/ \_\/\/_________/ \/_______/ \/__________/\/____________/\_\/ \_\/ * * On-chain Project-9 NFT, by SoftWave. **/ // File: @openzeppelin/contracts/utils/introspection/IERC165.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) 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); } // File: @openzeppelin/contracts/token/ERC721/IERC721.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol) 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); } // File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol) 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); } // File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol) 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); } // File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol) 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); } // File: @openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/utils/ERC721Utils.sol) 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)) } } } } } } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) 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; } } // File: @openzeppelin/contracts/utils/Panic.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol) 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) } } } // File: @openzeppelin/contracts/utils/math/SafeCast.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // 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)) } } } // File: @openzeppelin/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol) 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; } } // File: @openzeppelin/contracts/utils/math/SignedMath.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol) 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); } } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v5.2.0) (utils/Strings.sol) 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))) } } } // File: @openzeppelin/contracts/utils/introspection/ERC165.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) 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; } } // File: @openzeppelin/contracts/token/ERC721/ERC721.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/ERC721.sol) 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; } } // File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.20; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); } // File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.20; /** * @dev This implements an optional extension of {ERC721} defined in the ERC that adds enumerability * of all the token ids in the contract as well as all token ids owned by each account. * * CAUTION: {ERC721} extensions that implement custom `balanceOf` logic, such as {ERC721Consecutive}, * interfere with enumerability and should not be used together with {ERC721Enumerable}. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens; mapping(uint256 tokenId => uint256) private _ownedTokensIndex; uint256[] private _allTokens; mapping(uint256 tokenId => uint256) private _allTokensIndex; /** * @dev An `owner`'s token query was out of bounds for `index`. * * NOTE: The owner being `address(0)` indicates a global out of bounds index. */ error ERC721OutOfBoundsIndex(address owner, uint256 index); /** * @dev Batch mint is not allowed. */ error ERC721EnumerableForbiddenBatchMint(); /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) { if (index >= balanceOf(owner)) { revert ERC721OutOfBoundsIndex(owner, index); } return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual returns (uint256) { if (index >= totalSupply()) { revert ERC721OutOfBoundsIndex(address(0), index); } return _allTokens[index]; } /** * @dev See {ERC721-_update}. */ function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) { address previousOwner = super._update(to, tokenId, auth); if (previousOwner == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (previousOwner != to) { _removeTokenFromOwnerEnumeration(previousOwner, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (previousOwner != to) { _addTokenToOwnerEnumeration(to, tokenId); } return previousOwner; } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = balanceOf(to) - 1; _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = balanceOf(from); uint256 tokenIndex = _ownedTokensIndex[tokenId]; mapping(uint256 index => uint256) storage _ownedTokensByOwner = _ownedTokens[from]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokensByOwner[lastTokenIndex]; _ownedTokensByOwner[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokensByOwner[lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } /** * See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch */ function _increaseBalance(address account, uint128 amount) internal virtual override { if (amount > 0) { revert ERC721EnumerableForbiddenBatchMint(); } super._increaseBalance(account, amount); } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) 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); } } // File: @openzeppelin/contracts/utils/Base64.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/Base64.sol) pragma solidity ^0.8.20; /** * @dev Provides a set of functions to operate with Base64 strings. */ library Base64 { /** * @dev Base64 Encoding/Decoding Table * See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648 */ string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; string internal constant _TABLE_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; /** * @dev Converts a `bytes` to its Bytes64 `string` representation. */ function encode(bytes memory data) internal pure returns (string memory) { return _encode(data, _TABLE, true); } /** * @dev Converts a `bytes` to its Bytes64Url `string` representation. * Output is not padded with `=` as specified in https://www.rfc-editor.org/rfc/rfc4648[rfc4648]. */ function encodeURL(bytes memory data) internal pure returns (string memory) { return _encode(data, _TABLE_URL, false); } /** * @dev Internal table-agnostic conversion */ function _encode(bytes memory data, string memory table, bool withPadding) private pure returns (string memory) { /** * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol */ if (data.length == 0) return ""; // If padding is enabled, the final length should be `bytes` data length divided by 3 rounded up and then // multiplied by 4 so that it leaves room for padding the last chunk // - `data.length + 2` -> Prepare for division rounding up // - `/ 3` -> Number of 3-bytes chunks (rounded up) // - `4 *` -> 4 characters for each chunk // This is equivalent to: 4 * Math.ceil(data.length / 3) // // If padding is disabled, the final length should be `bytes` data length multiplied by 4/3 rounded up as // opposed to when padding is required to fill the last chunk. // - `4 * data.length` -> 4 characters for each chunk // - ` + 2` -> Prepare for division rounding up // - `/ 3` -> Number of 3-bytes chunks (rounded up) // This is equivalent to: Math.ceil((4 * data.length) / 3) uint256 resultLength = withPadding ? 4 * ((data.length + 2) / 3) : (4 * data.length + 2) / 3; string memory result = new string(resultLength); assembly ("memory-safe") { // Prepare the lookup table (skip the first "length" byte) let tablePtr := add(table, 1) // Prepare result pointer, jump over length let resultPtr := add(result, 0x20) let dataPtr := data let endPtr := add(data, mload(data)) // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and // set it to zero to make sure no dirty bytes are read in that section. let afterPtr := add(endPtr, 0x20) let afterCache := mload(afterPtr) mstore(afterPtr, 0x00) // Run over the input, 3 bytes at a time for { } lt(dataPtr, endPtr) { } { // Advance 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // To write each character, shift the 3 byte (24 bits) chunk // 4 times in blocks of 6 bits for each character (18, 12, 6, 0) // and apply logical AND with 0x3F to bitmask the least significant 6 bits. // Use this as an index into the lookup table, mload an entire word // so the desired character is in the least significant byte, and // mstore8 this least significant byte into the result and continue. mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F)))) resultPtr := add(resultPtr, 1) // Advance } // Reset the value that was cached mstore(afterPtr, afterCache) if withPadding { // When data `bytes` is not exactly 3 bytes long // it is padded with `=` characters at the end switch mod(mload(data), 3) case 1 { mstore8(sub(resultPtr, 1), 0x3d) mstore8(sub(resultPtr, 2), 0x3d) } case 2 { mstore8(sub(resultPtr, 1), 0x3d) } } } return result; } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) 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); } // File: contracts/ProjectNineData.sol /** * _ _ _ _ _ _ _ _ * /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ / /\ * / \ \ / \ \ / \ \ \ \ \ / \ \ / \ \ \_\ \ / / \ * / /\ \ \ / /\ \ \ / /\ \ \ /\ \_\ / /\ \ \ / /\ \ \ /\__ \ / / /\ \ * / / /\ \_\ / / /\ \_\ / / /\ \ \ / /\/_// / /\ \_\ / / /\ \ \ / /_ \ \ /_/ /\ \ \ * / / /_/ / // / /_/ / / / / / \ \_\ _ / / / / /_/_ \/_/ / / / \ \_\ / / /\ \ \ \ \ \_\ \ \ * / / /__\/ // / /__\/ / / / / / / //\ \ / / / / /____/\ / / / \/_/ / / / \/_/ \ \/__\ \ \ * / / /_____// / /_____/ / / / / / / \ \_\ / / / / /\____\/ / / / / / / \_____\ \ \ * / / / / / /\ \ \ / / /___/ / / / / /_/ / / / / /______ / / /________ / / / \ \ \ * / / / / / / \ \ \/ / /____\/ / / / /__\/ / / / /_______\/ / /_________\/_/ / \ \ \ * \/_/ \/_/ \_\/\/_________/ \/_______/ \/__________/\/____________/\_\/ \_\/ * * On-chain Project-9 NFT, by SoftWave. **/ pragma solidity ^0.8.0; contract ProjectNineData { address payable internal deployer; address payable public nftContract; bool private contractLocked = false; uint256 private constant CANVAS_SIZE = 24; uint256 private constant PIXEL_DATA_SIZE = CANVAS_SIZE * CANVAS_SIZE * 3; uint256 public constant MAX_LIMIT = 2222; Coordination public updateCoord; struct Trait { string traitType; string value; } struct Coordination { uint256 startX; uint256 startY; uint256 width; uint256 height; } struct NineData { bytes pixelData; Trait[] traits; bytes equippedWeapon; uint256 xp; } mapping(uint256 => NineData) private nineData; modifier onlyNFTContract() { require(msg.sender == nftContract, "Only NFTContract."); _; } modifier onlyDeployer() { require(msg.sender == deployer, "Only deployer."); _; } modifier unlocked() { require(!contractLocked, "Contract is locked."); _; } constructor() { deployer = payable(msg.sender); } function setNFTContract(address contractAddress) external onlyDeployer { nftContract = payable(contractAddress); } function setUpdateCoordination( uint256 startX, uint256 startY, uint256 width, uint256 height ) external onlyDeployer { require(startX + width <= CANVAS_SIZE, "Width out of bounds"); require(startY + height <= CANVAS_SIZE, "Height out of bounds"); updateCoord = Coordination(startX, startY, width, height); } function lockContract() external onlyDeployer unlocked { contractLocked = true; } function storePixelData(uint256 tokenId, bytes memory pixelData) external onlyDeployer unlocked { require(tokenId < MAX_LIMIT, "Invalid tokenId"); require( pixelData.length == PIXEL_DATA_SIZE, "Invalid pixel data length" ); nineData[tokenId].pixelData = pixelData; } function batchStorePixelData( uint256[] memory tokenIds, bytes[] memory pixelDataArray ) external onlyDeployer unlocked { require(tokenIds.length == pixelDataArray.length, "Mismatched arrays"); for (uint256 i = 0; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; bytes memory pixelData = pixelDataArray[i]; require(tokenId < MAX_LIMIT, "Invalid tokenId"); require( pixelData.length == PIXEL_DATA_SIZE, "Invalid pixel data length" ); nineData[tokenId].pixelData = pixelData; } } function storeTraits(uint256 tokenId, Trait[] memory traits) external onlyDeployer unlocked { require(traits.length > 0, "Traits cannot be empty"); delete nineData[tokenId].traits; for (uint256 i = 0; i < traits.length; i++) { nineData[tokenId].traits.push(traits[i]); } } function batchStoreTraits( uint256[] memory tokenIds, Trait[][] memory traitsArray ) external onlyDeployer unlocked { require(tokenIds.length == traitsArray.length, "Mismatched arrays"); for (uint256 i = 0; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; Trait[] memory traits = traitsArray[i]; delete nineData[tokenId].traits; for (uint256 j = 0; j < traits.length; j++) { nineData[tokenId].traits.push(traits[j]); } } } function getTraits(uint256 tokenId) external view returns (string memory) { require(nineData[tokenId].traits.length > 0, "Traits not set"); string memory jsonTraits = "["; for (uint256 i = 0; i < nineData[tokenId].traits.length; i++) { jsonTraits = string.concat( jsonTraits, '{"trait_type": "', nineData[tokenId].traits[i].traitType, '", "value": "', nineData[tokenId].traits[i].value, '"}' ); if (i < nineData[tokenId].traits.length - 1) { jsonTraits = string.concat(jsonTraits, ","); } } jsonTraits = string.concat(jsonTraits, "]"); return jsonTraits; } function getNineData(uint256 tokenId) external view returns (bytes memory) { require(tokenId < MAX_LIMIT, "Invalid tokenId"); require( nineData[tokenId].pixelData.length == PIXEL_DATA_SIZE, "Pixel data not set" ); return nineData[tokenId].pixelData; } function updateWeapon(uint256 tokenId, bytes memory colors) external onlyNFTContract { uint256 area = updateCoord.width * updateCoord.height; require(colors.length == area * 3, "Colors array length mismatch"); bytes storage weapon = nineData[tokenId].equippedWeapon; require(weapon.length == PIXEL_DATA_SIZE, "Invalid pixel data"); for (uint256 row = 0; row < updateCoord.height; row++) { for (uint256 col = 0; col < updateCoord.width; col++) { uint256 x = updateCoord.startX + col; uint256 y = updateCoord.startY + row; uint256 pixelIndex = (y * 24 + x) * 3; uint256 colorIndex = (row * updateCoord.width + col) * 3; weapon[pixelIndex] = colors[colorIndex]; weapon[pixelIndex + 1] = colors[colorIndex + 1]; weapon[pixelIndex + 2] = colors[colorIndex + 2]; } } if(nineData[tokenId].xp < 3) nineData[tokenId].xp += 1; } function updateTrait(uint256 tokenId, string memory traitType, string memory value) external onlyNFTContract { Trait[] storage traits = nineData[tokenId].traits; for (uint256 i = 0; i < traits.length; i++) { if (keccak256(bytes(traits[i].traitType)) == keccak256(bytes(traitType))) { traits[i].value = value; return; } } traits.push(Trait(traitType, value)); } function getEquippedWeapon(uint256 tokenId) external view returns (bytes memory) { return nineData[tokenId].equippedWeapon; } function train(uint256 tokenId) external onlyNFTContract { if(nineData[tokenId].xp < 3) nineData[tokenId].xp += 1; } function exercise(uint256 tokenId) external onlyNFTContract { if(nineData[tokenId].xp < 3) nineData[tokenId].xp += 1; } function getXP(uint256 tokenId) external view returns (uint256) { return nineData[tokenId].xp; } } // File: contracts/ProjectNineNFT.sol pragma solidity ^0.8.0; contract ProjectNineNFT is ERC721Enumerable, Ownable { ProjectNineData public dataContract; uint256 public immutable MAX_SUPPLY = 2222; uint256 public constant BASE_MAX_PER_WALLET = 3; uint256 public remaining; address payable public deployer; string private baseURI; mapping(address => bool) private WLAccounts; mapping(address => uint256) public mintCounts; uint256 private immutable seed; IERC20 public paymentToken; uint256 public mintPrice; uint256 public craftPrice; constructor(address dataContractAddress, address payable _deployer) ERC721("ProjectNine", "PNINE") Ownable(_deployer) { dataContract = ProjectNineData(dataContractAddress); deployer = _deployer; remaining = MAX_SUPPLY; seed = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), address(this)))); } modifier onlyDeployer { require(msg.sender == deployer, "Only Deployer."); _; } function setPaymentToken(address tokenAddress) external onlyDeployer { paymentToken = IERC20(tokenAddress); } function setPrices(uint256 _mintPrice, uint256 _craftPrice) external onlyDeployer { mintPrice = _mintPrice; craftPrice = _craftPrice; } function setWLAccounts(address[] memory participants) external onlyDeployer { for (uint256 i = 0; i < participants.length; i++) { WLAccounts[participants[i]] = true; } } function isInWhitelist(address participant) public view returns (bool) { return WLAccounts[participant]; } function mint() external { require(totalSupply() < MAX_SUPPLY, "Max supply reached"); require(mintPrice > 0, "Minting not enabled"); // Check mint limits uint256 maxAllowed = BASE_MAX_PER_WALLET; if (isInWhitelist(msg.sender)) { maxAllowed += 2; } require(mintCounts[msg.sender] < maxAllowed, "Exceeds mint limit"); // Process payment require( paymentToken.transferFrom(msg.sender, address(this), mintPrice), "Payment failed" ); uint256 tokenId = _getRandomTokenId(); _safeMint(msg.sender, tokenId); mintCounts[msg.sender]++; } function _getRandomTokenId() private returns (uint256) { require(remaining > 0, "All minted"); uint256 index = MAX_SUPPLY - remaining; uint256 tokenId = _permute(index); remaining--; return tokenId; } function tokenURI(uint256 tokenId) public view override returns (string memory) { require(tokenId < MAX_SUPPLY, "Token does not exist"); // Construct the external image URL and interactive URL string memory imageUrl = string(abi.encodePacked("https://p9-renderer.vercel.app/token/", toString(tokenId))); string memory externalUrl = string(abi.encodePacked("https://p9-renderer.vercel.app/token/", toString(tokenId))); string memory traits = dataContract.getTraits(tokenId); return string( abi.encodePacked( "data:application/json;base64,", Base64.encode( bytes( abi.encodePacked( '{"name":"Project Nine #', toString(tokenId), '", "description":"Project 9 - saving endangered creatures in uncharted realms.",', '"image":"', imageUrl, // Points to external SVG '", "external_url":"', externalUrl, // Interactive web version '", "attributes":', traits, '}' ) ) ) ) ); } function updatePixelData(uint256 tokenId, bytes memory newPixelData) external { require(ownerOf(tokenId) == msg.sender, "Not token owner"); dataContract.updateWeapon(tokenId, newPixelData); } function _permute(uint256 index) internal view returns (uint256) { uint256 prime = 2221; uint256 a = (seed % (prime - 1)) + 1; return (a * index) % prime; } function toString(uint256 value) internal pure returns (string memory) { if (value == 0) return "0"; uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } // Withdraw funds function function withdrawTokens(IERC20 token) external onlyDeployer { require(address(token) != address(0), "Invalid token"); token.transfer(deployer, token.balanceOf(address(this))); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"dataContractAddress","type":"address"},{"internalType":"address payable","name":"_deployer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","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":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","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":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BASE_MAX_PER_WALLET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"craftPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dataContract","outputs":[{"internalType":"contract ProjectNineData","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deployer","outputs":[{"internalType":"address payable","name":"","type":"address"}],"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":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"}],"name":"isInWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"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":"paymentToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"remaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"tokenAddress","type":"address"}],"name":"setPaymentToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintPrice","type":"uint256"},{"internalType":"uint256","name":"_craftPrice","type":"uint256"}],"name":"setPrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"participants","type":"address[]"}],"name":"setWLAccounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"newPixelData","type":"bytes"}],"name":"updatePixelData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040526108ae608090815250348015610018575f80fd5b50604051614ae3380380614ae3833981810160405281019061003a9190610373565b806040518060400160405280600b81526020017f50726f6a6563744e696e650000000000000000000000000000000000000000008152506040518060400160405280600581526020017f504e494e45000000000000000000000000000000000000000000000000000000815250815f90816100b591906105eb565b5080600190816100c591906105eb565b5050505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610138575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161012f91906106c9565b60405180910390fd5b6101478161021760201b60201c565b5081600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600d5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550608051600c819055506001436101de919061070f565b40306040516020016101f19291906107b0565b604051602081830303815290604052805190602001205f1c60a0818152505050506107db565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610307826102de565b9050919050565b610317816102fd565b8114610321575f80fd5b50565b5f815190506103328161030e565b92915050565b5f610342826102de565b9050919050565b61035281610338565b811461035c575f80fd5b50565b5f8151905061036d81610349565b92915050565b5f8060408385031215610389576103886102da565b5b5f61039685828601610324565b92505060206103a78582860161035f565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061042c57607f821691505b60208210810361043f5761043e6103e8565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026104a17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610466565b6104ab8683610466565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6104ef6104ea6104e5846104c3565b6104cc565b6104c3565b9050919050565b5f819050919050565b610508836104d5565b61051c610514826104f6565b848454610472565b825550505050565b5f90565b610530610524565b61053b8184846104ff565b505050565b5b8181101561055e576105535f82610528565b600181019050610541565b5050565b601f8211156105a35761057481610445565b61057d84610457565b8101602085101561058c578190505b6105a061059885610457565b830182610540565b50505b505050565b5f82821c905092915050565b5f6105c35f19846008026105a8565b1980831691505092915050565b5f6105db83836105b4565b9150826002028217905092915050565b6105f4826103b1565b67ffffffffffffffff81111561060d5761060c6103bb565b5b6106178254610415565b610622828285610562565b5f60209050601f831160018114610653575f8415610641578287015190505b61064b85826105d0565b8655506106b2565b601f19841661066186610445565b5f5b8281101561068857848901518255600182019150602085019450602081019050610663565b868310156106a557848901516106a1601f8916826105b4565b8355505b6001600288020188555050505b505050505050565b6106c3816102fd565b82525050565b5f6020820190506106dc5f8301846106ba565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610719826104c3565b9150610724836104c3565b925082820390508181111561073c5761073b6106e2565b5b92915050565b5f819050919050565b5f819050919050565b61076561076082610742565b61074b565b82525050565b5f8160601b9050919050565b5f6107818261076b565b9050919050565b5f61079282610777565b9050919050565b6107aa6107a5826102fd565b610788565b82525050565b5f6107bb8285610754565b6020820191506107cb8284610799565b6014820191508190509392505050565b60805160a0516142d26108115f395f6123f001525f81816108f601528181610e66015281816115160152611a0501526142d25ff3fe608060405234801561000f575f80fd5b506004361061020f575f3560e01c806353277879116101235780638099b002116100ab578063b88d4fde1161007a578063b88d4fde146105ed578063c87b56dd14610609578063d5f3948814610639578063e985e9c514610657578063f2fde38b146106875761020f565b80638099b002146105775780638da5cb5b1461059557806395d89b41146105b3578063a22cb465146105d15761020f565b806367b06aee116100f257806367b06aee146104e75780636817c76c146105035780636a326ab11461052157806370a082311461053d578063715018a61461056d5761020f565b8063532778791461044b57806355234ec01461047b578063584430e6146104995780636352211e146104b75761020f565b806318160ddd116101a65780633013ce29116101755780633013ce29146103a757806332cb6b0c146103c557806342842e0e146103e357806349df728c146103ff5780634f6ccce71461041b5761020f565b806318160ddd146103215780632061cea71461033f57806323b872dd1461035b5780632f745c59146103775761020f565b8063095ea7b3116101e2578063095ea7b3146102ad57806309fd8212146102c95780630d668818146102f95780631249c58b146103175761020f565b806301ffc9a71461021357806305fefda71461024357806306fdde031461025f578063081812fc1461027d575b5f80fd5b61022d60048036038101906102289190612d3d565b6106a3565b60405161023a9190612d82565b60405180910390f35b61025d60048036038101906102589190612dce565b61071c565b005b6102676107bd565b6040516102749190612e7c565b60405180910390f35b61029760048036038101906102929190612e9c565b61084c565b6040516102a49190612f06565b60405180910390f35b6102c760048036038101906102c29190612f49565b610867565b005b6102e360048036038101906102de9190612f87565b61087d565b6040516102f09190612d82565b60405180910390f35b6103016108cf565b60405161030e919061300d565b60405180910390f35b61031f6108f4565b005b610329610b8d565b6040516103369190613035565b60405180910390f35b6103596004803603810190610354919061317a565b610b99565b005b610375600480360381019061037091906131d4565b610c9c565b005b610391600480360381019061038c9190612f49565b610d9b565b60405161039e9190613035565b60405180910390f35b6103af610e3f565b6040516103bc9190613244565b60405180910390f35b6103cd610e64565b6040516103da9190613035565b60405180910390f35b6103fd60048036038101906103f891906131d4565b610e88565b005b61041960048036038101906104149190613298565b610ea7565b005b61043560048036038101906104309190612e9c565b6110bb565b6040516104429190613035565b60405180910390f35b61046560048036038101906104609190612f87565b61112d565b6040516104729190613035565b60405180910390f35b610483611142565b6040516104909190613035565b60405180910390f35b6104a1611148565b6040516104ae9190613035565b60405180910390f35b6104d160048036038101906104cc9190612e9c565b61114e565b6040516104de9190612f06565b60405180910390f35b61050160048036038101906104fc9190613387565b61115f565b005b61050b611279565b6040516105189190613035565b60405180910390f35b61053b60048036038101906105369190612f87565b61127f565b005b61055760048036038101906105529190612f87565b611351565b6040516105649190613035565b60405180910390f35b610575611407565b005b61057f61141a565b60405161058c9190613035565b60405180910390f35b61059d61141f565b6040516105aa9190612f06565b60405180910390f35b6105bb611447565b6040516105c89190612e7c565b60405180910390f35b6105eb60048036038101906105e691906133f8565b6114d7565b005b61060760048036038101906106029190613436565b6114ed565b005b610623600480360381019061061e9190612e9c565b611512565b6040516106309190612e7c565b60405180910390f35b6106416116ca565b60405161064e91906134d6565b60405180910390f35b610671600480360381019061066c91906134ef565b6116ef565b60405161067e9190612d82565b60405180910390f35b6106a1600480360381019061069c9190612f87565b61177d565b005b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610715575061071482611801565b5b9050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107a290613577565b60405180910390fd5b81601281905550806013819055505050565b60605f80546107cb906135c2565b80601f01602080910402602001604051908101604052809291908181526020018280546107f7906135c2565b80156108425780601f1061081957610100808354040283529160200191610842565b820191905f5260205f20905b81548152906001019060200180831161082557829003601f168201915b5050505050905090565b5f610856826118e2565b5061086082611968565b9050919050565b61087982826108746119a1565b6119a8565b5050565b5f600f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000061091d610b8d565b1061095d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109549061363c565b60405180910390fd5b5f601254116109a1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610998906136a4565b60405180910390fd5b5f600390506109af3361087d565b156109c4576002816109c191906136ef565b90505b8060105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410610a43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a3a9061376c565b60405180910390fd5b60115f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33306012546040518463ffffffff1660e01b8152600401610aa39392919061378a565b6020604051808303815f875af1158015610abf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae391906137d3565b610b22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1990613848565b60405180910390fd5b5f610b2b6119ba565b9050610b373382611a5b565b60105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610b8490613866565b91905055505050565b5f600880549050905090565b3373ffffffffffffffffffffffffffffffffffffffff16610bb98361114e565b73ffffffffffffffffffffffffffffffffffffffff1614610c0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c06906138f7565b60405180910390fd5b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d5b959f483836040518363ffffffff1660e01b8152600401610c6b929190613967565b5f604051808303815f87803b158015610c82575f80fd5b505af1158015610c94573d5f803e3d5ffd5b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d0c575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401610d039190612f06565b60405180910390fd5b5f610d1f8383610d1a6119a1565b611a78565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d95578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610d8c93929190613995565b60405180910390fd5b50505050565b5f610da583611351565b8210610dea5782826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610de19291906139ca565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b60115f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b610ea283838360405180602001604052805f8152506114ed565b505050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610f36576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2d90613577565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610fa4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9b90613a3b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161101b9190612f06565b602060405180830381865afa158015611036573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061105a9190613a6d565b6040518363ffffffff1660e01b8152600401611077929190613ab8565b6020604051808303815f875af1158015611093573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110b791906137d3565b5050565b5f6110c4610b8d565b8210611109575f826040517fa57d13dc0000000000000000000000000000000000000000000000000000000081526004016111009291906139ca565b60405180910390fd5b6008828154811061111d5761111c613adf565b5b905f5260205f2001549050919050565b6010602052805f5260405f205f915090505481565b600c5481565b60135481565b5f611158826118e2565b9050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111e590613577565b60405180910390fd5b5f5b8151811015611275576001600f5f84848151811061121157611210613adf565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555080806001019150506111f0565b5050565b60125481565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461130e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130590613577565b60405180910390fd5b8060115f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036113c2575f6040517f89c62b640000000000000000000000000000000000000000000000000000000081526004016113b99190612f06565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61140f611b92565b6114185f611c19565b565b600381565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054611456906135c2565b80601f0160208091040260200160405190810160405280929190818152602001828054611482906135c2565b80156114cd5780601f106114a4576101008083540402835291602001916114cd565b820191905f5260205f20905b8154815290600101906020018083116114b057829003601f168201915b5050505050905090565b6114e96114e26119a1565b8383611cdc565b5050565b6114f8848484610c9c565b61150c6115036119a1565b85858585611e45565b50505050565b60607f00000000000000000000000000000000000000000000000000000000000000008210611576576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156d90613b56565b60405180910390fd5b5f61158083611ff1565b6040516020016115909190613c1e565b60405160208183030381529060405290505f6115ab84611ff1565b6040516020016115bb9190613c1e565b60405160208183030381529060405290505f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e1dc0761866040518263ffffffff1660e01b81526004016116279190613035565b5f60405180830381865afa158015611641573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906116699190613cdd565b90506116a161167786611ff1565b84848460405160200161168d9493929190613f2c565b60405160208183030381529060405261214a565b6040516020016116b19190613ff5565b6040516020818303038152906040529350505050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b611785611b92565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036117f5575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016117ec9190612f06565b60405180910390fd5b6117fe81611c19565b50565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806118cb57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806118db57506118da82612177565b5b9050919050565b5f806118ed836121e0565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361195f57826040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016119569190613035565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6119b58383836001612219565b505050565b5f80600c54116119ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f690614060565b60405180910390fd5b5f600c547f0000000000000000000000000000000000000000000000000000000000000000611a2e919061407e565b90505f611a3a826123d8565b9050600c5f815480929190611a4e906140b1565b9190505550809250505090565b611a74828260405180602001604052805f815250612445565b5050565b5f80611a85858585612468565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ac857611ac384612673565b611b07565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b0657611b0581856126b7565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611b4857611b438461278e565b611b87565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b8657611b85858561284e565b5b5b809150509392505050565b611b9a6119a1565b73ffffffffffffffffffffffffffffffffffffffff16611bb861141f565b73ffffffffffffffffffffffffffffffffffffffff1614611c1757611bdb6119a1565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611c0e9190612f06565b60405180910390fd5b565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d4c57816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611d439190612f06565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611e389190612d82565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115611fea578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b8152600401611ea394939291906140d8565b6020604051808303815f875af1925050508015611ede57506040513d601f19601f82011682018060405250810190611edb9190614136565b60015b611f5f573d805f8114611f0c576040519150601f19603f3d011682016040523d82523d5f602084013e611f11565b606091505b505f815103611f5757836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611f4e9190612f06565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611fe857836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611fdf9190612f06565b60405180910390fd5b505b5050505050565b60605f8203612037576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612145565b5f8290505f5b5f821461206657808061204f90613866565b915050600a8261205f919061418e565b915061203d565b5f8167ffffffffffffffff81111561208157612080613056565b5b6040519080825280601f01601f1916602001820160405280156120b35781602001600182028036833780820191505090505b5090505b5f851461213e576001826120cb919061407e565b9150600a856120da91906141be565b60306120e691906136ef565b60f81b8183815181106120fc576120fb613adf565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a85612137919061418e565b94506120b7565b8093505050505b919050565b60606121708260405180606001604052806040815260200161425d6040913960016128d2565b9050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061225157505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15612383575f612260846118e2565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156122ca57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156122dd57506122db81846116ef565b155b1561231f57826040517fa9fbf51f0000000000000000000000000000000000000000000000000000000081526004016123169190612f06565b60405180910390fd5b811561238157838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b5f806108ad90505f600180836123ee919061407e565b7f000000000000000000000000000000000000000000000000000000000000000061241991906141be565b61242391906136ef565b905081848261243291906141ee565b61243c91906141be565b92505050919050565b61244f8383612a61565b61246361245a6119a1565b5f858585611e45565b505050565b5f80612473846121e0565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146124b4576124b3818486612b54565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461253f576124f35f855f80612219565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146125be57600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f6126c183611351565b90505f60075f8481526020019081526020015f205490505f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050828214612760575f815f8581526020019081526020015f2054905080825f8581526020019081526020015f20819055508260075f8381526020019081526020015f2081905550505b60075f8581526020019081526020015f205f9055805f8481526020019081526020015f205f90555050505050565b5f60016008805490506127a1919061407e565b90505f60095f8481526020019081526020015f205490505f600883815481106127cd576127cc613adf565b5b905f5260205f200154905080600883815481106127ed576127ec613adf565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f905560088054806128355761283461422f565b5b600190038181905f5260205f20015f9055905550505050565b5f600161285a84611351565b612864919061407e565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b60605f8451036128f25760405180602001604052805f8152509050612a5a565b5f8261292357600360028651600461290a91906141ee565b61291491906136ef565b61291e919061418e565b61294a565b60036002865161293391906136ef565b61293d919061418e565b600461294991906141ee565b5b90505f8167ffffffffffffffff81111561296757612966613056565b5b6040519080825280601f01601f1916602001820160405280156129995781602001600182028036833780820191505090505b509050600185016020820187885189016020810180515f82525b82841015612a0e576003840193508351603f8160121c168701518653600186019550603f81600c1c168701518653600186019550603f8160061c168701518653600186019550603f81168701518653600186019550506129b3565b8082528915612a4e5760038c510660018114612a315760028114612a4457612a4c565b603d6001870353603d6002870353612a4c565b603d60018703535b505b50505050505080925050505b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612ad1575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612ac89190612f06565b60405180910390fd5b5f612add83835f611a78565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612b4f575f6040517f73c6ac6e000000000000000000000000000000000000000000000000000000008152600401612b469190612f06565b60405180910390fd5b505050565b612b5f838383612c17565b612c12575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612bd357806040517f7e273289000000000000000000000000000000000000000000000000000000008152600401612bca9190613035565b60405180910390fd5b81816040517f177e802f000000000000000000000000000000000000000000000000000000008152600401612c099291906139ca565b60405180910390fd5b505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612cce57508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612c8f5750612c8e84846116ef565b5b80612ccd57508273ffffffffffffffffffffffffffffffffffffffff16612cb583611968565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612d1c81612ce8565b8114612d26575f80fd5b50565b5f81359050612d3781612d13565b92915050565b5f60208284031215612d5257612d51612ce0565b5b5f612d5f84828501612d29565b91505092915050565b5f8115159050919050565b612d7c81612d68565b82525050565b5f602082019050612d955f830184612d73565b92915050565b5f819050919050565b612dad81612d9b565b8114612db7575f80fd5b50565b5f81359050612dc881612da4565b92915050565b5f8060408385031215612de457612de3612ce0565b5b5f612df185828601612dba565b9250506020612e0285828601612dba565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612e4e82612e0c565b612e588185612e16565b9350612e68818560208601612e26565b612e7181612e34565b840191505092915050565b5f6020820190508181035f830152612e948184612e44565b905092915050565b5f60208284031215612eb157612eb0612ce0565b5b5f612ebe84828501612dba565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612ef082612ec7565b9050919050565b612f0081612ee6565b82525050565b5f602082019050612f195f830184612ef7565b92915050565b612f2881612ee6565b8114612f32575f80fd5b50565b5f81359050612f4381612f1f565b92915050565b5f8060408385031215612f5f57612f5e612ce0565b5b5f612f6c85828601612f35565b9250506020612f7d85828601612dba565b9150509250929050565b5f60208284031215612f9c57612f9b612ce0565b5b5f612fa984828501612f35565b91505092915050565b5f819050919050565b5f612fd5612fd0612fcb84612ec7565b612fb2565b612ec7565b9050919050565b5f612fe682612fbb565b9050919050565b5f612ff782612fdc565b9050919050565b61300781612fed565b82525050565b5f6020820190506130205f830184612ffe565b92915050565b61302f81612d9b565b82525050565b5f6020820190506130485f830184613026565b92915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61308c82612e34565b810181811067ffffffffffffffff821117156130ab576130aa613056565b5b80604052505050565b5f6130bd612cd7565b90506130c98282613083565b919050565b5f67ffffffffffffffff8211156130e8576130e7613056565b5b6130f182612e34565b9050602081019050919050565b828183375f83830152505050565b5f61311e613119846130ce565b6130b4565b90508281526020810184848401111561313a57613139613052565b5b6131458482856130fe565b509392505050565b5f82601f8301126131615761316061304e565b5b813561317184826020860161310c565b91505092915050565b5f80604083850312156131905761318f612ce0565b5b5f61319d85828601612dba565b925050602083013567ffffffffffffffff8111156131be576131bd612ce4565b5b6131ca8582860161314d565b9150509250929050565b5f805f606084860312156131eb576131ea612ce0565b5b5f6131f886828701612f35565b935050602061320986828701612f35565b925050604061321a86828701612dba565b9150509250925092565b5f61322e82612fdc565b9050919050565b61323e81613224565b82525050565b5f6020820190506132575f830184613235565b92915050565b5f61326782612ee6565b9050919050565b6132778161325d565b8114613281575f80fd5b50565b5f813590506132928161326e565b92915050565b5f602082840312156132ad576132ac612ce0565b5b5f6132ba84828501613284565b91505092915050565b5f67ffffffffffffffff8211156132dd576132dc613056565b5b602082029050602081019050919050565b5f80fd5b5f6133046132ff846132c3565b6130b4565b90508083825260208201905060208402830185811115613327576133266132ee565b5b835b81811015613350578061333c8882612f35565b845260208401935050602081019050613329565b5050509392505050565b5f82601f83011261336e5761336d61304e565b5b813561337e8482602086016132f2565b91505092915050565b5f6020828403121561339c5761339b612ce0565b5b5f82013567ffffffffffffffff8111156133b9576133b8612ce4565b5b6133c58482850161335a565b91505092915050565b6133d781612d68565b81146133e1575f80fd5b50565b5f813590506133f2816133ce565b92915050565b5f806040838503121561340e5761340d612ce0565b5b5f61341b85828601612f35565b925050602061342c858286016133e4565b9150509250929050565b5f805f806080858703121561344e5761344d612ce0565b5b5f61345b87828801612f35565b945050602061346c87828801612f35565b935050604061347d87828801612dba565b925050606085013567ffffffffffffffff81111561349e5761349d612ce4565b5b6134aa8782880161314d565b91505092959194509250565b5f6134c082612ec7565b9050919050565b6134d0816134b6565b82525050565b5f6020820190506134e95f8301846134c7565b92915050565b5f806040838503121561350557613504612ce0565b5b5f61351285828601612f35565b925050602061352385828601612f35565b9150509250929050565b7f4f6e6c79204465706c6f7965722e0000000000000000000000000000000000005f82015250565b5f613561600e83612e16565b915061356c8261352d565b602082019050919050565b5f6020820190508181035f83015261358e81613555565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806135d957607f821691505b6020821081036135ec576135eb613595565b5b50919050565b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f613626601283612e16565b9150613631826135f2565b602082019050919050565b5f6020820190508181035f8301526136538161361a565b9050919050565b7f4d696e74696e67206e6f7420656e61626c6564000000000000000000000000005f82015250565b5f61368e601383612e16565b91506136998261365a565b602082019050919050565b5f6020820190508181035f8301526136bb81613682565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6136f982612d9b565b915061370483612d9b565b925082820190508082111561371c5761371b6136c2565b5b92915050565b7f45786365656473206d696e74206c696d697400000000000000000000000000005f82015250565b5f613756601283612e16565b915061376182613722565b602082019050919050565b5f6020820190508181035f8301526137838161374a565b9050919050565b5f60608201905061379d5f830186612ef7565b6137aa6020830185612ef7565b6137b76040830184613026565b949350505050565b5f815190506137cd816133ce565b92915050565b5f602082840312156137e8576137e7612ce0565b5b5f6137f5848285016137bf565b91505092915050565b7f5061796d656e74206661696c65640000000000000000000000000000000000005f82015250565b5f613832600e83612e16565b915061383d826137fe565b602082019050919050565b5f6020820190508181035f83015261385f81613826565b9050919050565b5f61387082612d9b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036138a2576138a16136c2565b5b600182019050919050565b7f4e6f7420746f6b656e206f776e657200000000000000000000000000000000005f82015250565b5f6138e1600f83612e16565b91506138ec826138ad565b602082019050919050565b5f6020820190508181035f83015261390e816138d5565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f61393982613915565b613943818561391f565b9350613953818560208601612e26565b61395c81612e34565b840191505092915050565b5f60408201905061397a5f830185613026565b818103602083015261398c818461392f565b90509392505050565b5f6060820190506139a85f830186612ef7565b6139b56020830185613026565b6139c26040830184612ef7565b949350505050565b5f6040820190506139dd5f830185612ef7565b6139ea6020830184613026565b9392505050565b7f496e76616c696420746f6b656e000000000000000000000000000000000000005f82015250565b5f613a25600d83612e16565b9150613a30826139f1565b602082019050919050565b5f6020820190508181035f830152613a5281613a19565b9050919050565b5f81519050613a6781612da4565b92915050565b5f60208284031215613a8257613a81612ce0565b5b5f613a8f84828501613a59565b91505092915050565b5f613aa282612fdc565b9050919050565b613ab281613a98565b82525050565b5f604082019050613acb5f830185613aa9565b613ad86020830184613026565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f546f6b656e20646f6573206e6f742065786973740000000000000000000000005f82015250565b5f613b40601483612e16565b9150613b4b82613b0c565b602082019050919050565b5f6020820190508181035f830152613b6d81613b34565b9050919050565b5f81905092915050565b7f68747470733a2f2f70392d72656e64657265722e76657263656c2e6170702f745f8201527f6f6b656e2f000000000000000000000000000000000000000000000000000000602082015250565b5f613bd8602583613b74565b9150613be382613b7e565b602582019050919050565b5f613bf882612e0c565b613c028185613b74565b9350613c12818560208601612e26565b80840191505092915050565b5f613c2882613bcc565b9150613c348284613bee565b915081905092915050565b5f67ffffffffffffffff821115613c5957613c58613056565b5b613c6282612e34565b9050602081019050919050565b5f613c81613c7c84613c3f565b6130b4565b905082815260208101848484011115613c9d57613c9c613052565b5b613ca8848285612e26565b509392505050565b5f82601f830112613cc457613cc361304e565b5b8151613cd4848260208601613c6f565b91505092915050565b5f60208284031215613cf257613cf1612ce0565b5b5f82015167ffffffffffffffff811115613d0f57613d0e612ce4565b5b613d1b84828501613cb0565b91505092915050565b7f7b226e616d65223a2250726f6a656374204e696e6520230000000000000000005f82015250565b5f613d58601783613b74565b9150613d6382613d24565b601782019050919050565b7f222c20226465736372697074696f6e223a2250726f6a6563742039202d2073615f8201527f76696e6720656e64616e67657265642063726561747572657320696e20756e6360208201527f686172746564207265616c6d732e222c00000000000000000000000000000000604082015250565b5f613dee605083613b74565b9150613df982613d6e565b605082019050919050565b7f22696d616765223a2200000000000000000000000000000000000000000000005f82015250565b5f613e38600983613b74565b9150613e4382613e04565b600982019050919050565b7f222c202265787465726e616c5f75726c223a22000000000000000000000000005f82015250565b5f613e82601383613b74565b9150613e8d82613e4e565b601382019050919050565b7f222c202261747472696275746573223a000000000000000000000000000000005f82015250565b5f613ecc601083613b74565b9150613ed782613e98565b601082019050919050565b7f7d000000000000000000000000000000000000000000000000000000000000005f82015250565b5f613f16600183613b74565b9150613f2182613ee2565b600182019050919050565b5f613f3682613d4c565b9150613f428287613bee565b9150613f4d82613de2565b9150613f5882613e2c565b9150613f648286613bee565b9150613f6f82613e76565b9150613f7b8285613bee565b9150613f8682613ec0565b9150613f928284613bee565b9150613f9d82613f0a565b915081905095945050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f613fdf601d83613b74565b9150613fea82613fab565b601d82019050919050565b5f613fff82613fd3565b915061400b8284613bee565b915081905092915050565b7f416c6c206d696e746564000000000000000000000000000000000000000000005f82015250565b5f61404a600a83612e16565b915061405582614016565b602082019050919050565b5f6020820190508181035f8301526140778161403e565b9050919050565b5f61408882612d9b565b915061409383612d9b565b92508282039050818111156140ab576140aa6136c2565b5b92915050565b5f6140bb82612d9b565b91505f82036140cd576140cc6136c2565b5b600182039050919050565b5f6080820190506140eb5f830187612ef7565b6140f86020830186612ef7565b6141056040830185613026565b8181036060830152614117818461392f565b905095945050505050565b5f8151905061413081612d13565b92915050565b5f6020828403121561414b5761414a612ce0565b5b5f61415884828501614122565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61419882612d9b565b91506141a383612d9b565b9250826141b3576141b2614161565b5b828204905092915050565b5f6141c882612d9b565b91506141d383612d9b565b9250826141e3576141e2614161565b5b828206905092915050565b5f6141f882612d9b565b915061420383612d9b565b925082820261421181612d9b565b91508282048414831517614228576142276136c2565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220fd85b315a71bafd2ff8a13d5164a8c7845d126c1a3062671ef896ad55d97ac4c64736f6c634300081a00330000000000000000000000000200f5dbe0e50c8d21d035983bf444f86c5908ea000000000000000000000000b931e339b4f5eb3d4d039ce1451426754063c711
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061020f575f3560e01c806353277879116101235780638099b002116100ab578063b88d4fde1161007a578063b88d4fde146105ed578063c87b56dd14610609578063d5f3948814610639578063e985e9c514610657578063f2fde38b146106875761020f565b80638099b002146105775780638da5cb5b1461059557806395d89b41146105b3578063a22cb465146105d15761020f565b806367b06aee116100f257806367b06aee146104e75780636817c76c146105035780636a326ab11461052157806370a082311461053d578063715018a61461056d5761020f565b8063532778791461044b57806355234ec01461047b578063584430e6146104995780636352211e146104b75761020f565b806318160ddd116101a65780633013ce29116101755780633013ce29146103a757806332cb6b0c146103c557806342842e0e146103e357806349df728c146103ff5780634f6ccce71461041b5761020f565b806318160ddd146103215780632061cea71461033f57806323b872dd1461035b5780632f745c59146103775761020f565b8063095ea7b3116101e2578063095ea7b3146102ad57806309fd8212146102c95780630d668818146102f95780631249c58b146103175761020f565b806301ffc9a71461021357806305fefda71461024357806306fdde031461025f578063081812fc1461027d575b5f80fd5b61022d60048036038101906102289190612d3d565b6106a3565b60405161023a9190612d82565b60405180910390f35b61025d60048036038101906102589190612dce565b61071c565b005b6102676107bd565b6040516102749190612e7c565b60405180910390f35b61029760048036038101906102929190612e9c565b61084c565b6040516102a49190612f06565b60405180910390f35b6102c760048036038101906102c29190612f49565b610867565b005b6102e360048036038101906102de9190612f87565b61087d565b6040516102f09190612d82565b60405180910390f35b6103016108cf565b60405161030e919061300d565b60405180910390f35b61031f6108f4565b005b610329610b8d565b6040516103369190613035565b60405180910390f35b6103596004803603810190610354919061317a565b610b99565b005b610375600480360381019061037091906131d4565b610c9c565b005b610391600480360381019061038c9190612f49565b610d9b565b60405161039e9190613035565b60405180910390f35b6103af610e3f565b6040516103bc9190613244565b60405180910390f35b6103cd610e64565b6040516103da9190613035565b60405180910390f35b6103fd60048036038101906103f891906131d4565b610e88565b005b61041960048036038101906104149190613298565b610ea7565b005b61043560048036038101906104309190612e9c565b6110bb565b6040516104429190613035565b60405180910390f35b61046560048036038101906104609190612f87565b61112d565b6040516104729190613035565b60405180910390f35b610483611142565b6040516104909190613035565b60405180910390f35b6104a1611148565b6040516104ae9190613035565b60405180910390f35b6104d160048036038101906104cc9190612e9c565b61114e565b6040516104de9190612f06565b60405180910390f35b61050160048036038101906104fc9190613387565b61115f565b005b61050b611279565b6040516105189190613035565b60405180910390f35b61053b60048036038101906105369190612f87565b61127f565b005b61055760048036038101906105529190612f87565b611351565b6040516105649190613035565b60405180910390f35b610575611407565b005b61057f61141a565b60405161058c9190613035565b60405180910390f35b61059d61141f565b6040516105aa9190612f06565b60405180910390f35b6105bb611447565b6040516105c89190612e7c565b60405180910390f35b6105eb60048036038101906105e691906133f8565b6114d7565b005b61060760048036038101906106029190613436565b6114ed565b005b610623600480360381019061061e9190612e9c565b611512565b6040516106309190612e7c565b60405180910390f35b6106416116ca565b60405161064e91906134d6565b60405180910390f35b610671600480360381019061066c91906134ef565b6116ef565b60405161067e9190612d82565b60405180910390f35b6106a1600480360381019061069c9190612f87565b61177d565b005b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610715575061071482611801565b5b9050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107a290613577565b60405180910390fd5b81601281905550806013819055505050565b60605f80546107cb906135c2565b80601f01602080910402602001604051908101604052809291908181526020018280546107f7906135c2565b80156108425780601f1061081957610100808354040283529160200191610842565b820191905f5260205f20905b81548152906001019060200180831161082557829003601f168201915b5050505050905090565b5f610856826118e2565b5061086082611968565b9050919050565b61087982826108746119a1565b6119a8565b5050565b5f600f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000008ae61091d610b8d565b1061095d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109549061363c565b60405180910390fd5b5f601254116109a1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610998906136a4565b60405180910390fd5b5f600390506109af3361087d565b156109c4576002816109c191906136ef565b90505b8060105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410610a43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a3a9061376c565b60405180910390fd5b60115f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33306012546040518463ffffffff1660e01b8152600401610aa39392919061378a565b6020604051808303815f875af1158015610abf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae391906137d3565b610b22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1990613848565b60405180910390fd5b5f610b2b6119ba565b9050610b373382611a5b565b60105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610b8490613866565b91905055505050565b5f600880549050905090565b3373ffffffffffffffffffffffffffffffffffffffff16610bb98361114e565b73ffffffffffffffffffffffffffffffffffffffff1614610c0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c06906138f7565b60405180910390fd5b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d5b959f483836040518363ffffffff1660e01b8152600401610c6b929190613967565b5f604051808303815f87803b158015610c82575f80fd5b505af1158015610c94573d5f803e3d5ffd5b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d0c575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401610d039190612f06565b60405180910390fd5b5f610d1f8383610d1a6119a1565b611a78565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d95578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610d8c93929190613995565b60405180910390fd5b50505050565b5f610da583611351565b8210610dea5782826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610de19291906139ca565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b60115f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000008ae81565b610ea283838360405180602001604052805f8152506114ed565b505050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610f36576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2d90613577565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610fa4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9b90613a3b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161101b9190612f06565b602060405180830381865afa158015611036573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061105a9190613a6d565b6040518363ffffffff1660e01b8152600401611077929190613ab8565b6020604051808303815f875af1158015611093573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110b791906137d3565b5050565b5f6110c4610b8d565b8210611109575f826040517fa57d13dc0000000000000000000000000000000000000000000000000000000081526004016111009291906139ca565b60405180910390fd5b6008828154811061111d5761111c613adf565b5b905f5260205f2001549050919050565b6010602052805f5260405f205f915090505481565b600c5481565b60135481565b5f611158826118e2565b9050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111e590613577565b60405180910390fd5b5f5b8151811015611275576001600f5f84848151811061121157611210613adf565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555080806001019150506111f0565b5050565b60125481565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461130e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130590613577565b60405180910390fd5b8060115f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036113c2575f6040517f89c62b640000000000000000000000000000000000000000000000000000000081526004016113b99190612f06565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61140f611b92565b6114185f611c19565b565b600381565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054611456906135c2565b80601f0160208091040260200160405190810160405280929190818152602001828054611482906135c2565b80156114cd5780601f106114a4576101008083540402835291602001916114cd565b820191905f5260205f20905b8154815290600101906020018083116114b057829003601f168201915b5050505050905090565b6114e96114e26119a1565b8383611cdc565b5050565b6114f8848484610c9c565b61150c6115036119a1565b85858585611e45565b50505050565b60607f00000000000000000000000000000000000000000000000000000000000008ae8210611576576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156d90613b56565b60405180910390fd5b5f61158083611ff1565b6040516020016115909190613c1e565b60405160208183030381529060405290505f6115ab84611ff1565b6040516020016115bb9190613c1e565b60405160208183030381529060405290505f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e1dc0761866040518263ffffffff1660e01b81526004016116279190613035565b5f60405180830381865afa158015611641573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906116699190613cdd565b90506116a161167786611ff1565b84848460405160200161168d9493929190613f2c565b60405160208183030381529060405261214a565b6040516020016116b19190613ff5565b6040516020818303038152906040529350505050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b611785611b92565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036117f5575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016117ec9190612f06565b60405180910390fd5b6117fe81611c19565b50565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806118cb57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806118db57506118da82612177565b5b9050919050565b5f806118ed836121e0565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361195f57826040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016119569190613035565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6119b58383836001612219565b505050565b5f80600c54116119ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f690614060565b60405180910390fd5b5f600c547f00000000000000000000000000000000000000000000000000000000000008ae611a2e919061407e565b90505f611a3a826123d8565b9050600c5f815480929190611a4e906140b1565b9190505550809250505090565b611a74828260405180602001604052805f815250612445565b5050565b5f80611a85858585612468565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ac857611ac384612673565b611b07565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b0657611b0581856126b7565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611b4857611b438461278e565b611b87565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b8657611b85858561284e565b5b5b809150509392505050565b611b9a6119a1565b73ffffffffffffffffffffffffffffffffffffffff16611bb861141f565b73ffffffffffffffffffffffffffffffffffffffff1614611c1757611bdb6119a1565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611c0e9190612f06565b60405180910390fd5b565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d4c57816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611d439190612f06565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611e389190612d82565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115611fea578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b8152600401611ea394939291906140d8565b6020604051808303815f875af1925050508015611ede57506040513d601f19601f82011682018060405250810190611edb9190614136565b60015b611f5f573d805f8114611f0c576040519150601f19603f3d011682016040523d82523d5f602084013e611f11565b606091505b505f815103611f5757836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611f4e9190612f06565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611fe857836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611fdf9190612f06565b60405180910390fd5b505b5050505050565b60605f8203612037576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612145565b5f8290505f5b5f821461206657808061204f90613866565b915050600a8261205f919061418e565b915061203d565b5f8167ffffffffffffffff81111561208157612080613056565b5b6040519080825280601f01601f1916602001820160405280156120b35781602001600182028036833780820191505090505b5090505b5f851461213e576001826120cb919061407e565b9150600a856120da91906141be565b60306120e691906136ef565b60f81b8183815181106120fc576120fb613adf565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a85612137919061418e565b94506120b7565b8093505050505b919050565b60606121708260405180606001604052806040815260200161425d6040913960016128d2565b9050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061225157505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15612383575f612260846118e2565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156122ca57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156122dd57506122db81846116ef565b155b1561231f57826040517fa9fbf51f0000000000000000000000000000000000000000000000000000000081526004016123169190612f06565b60405180910390fd5b811561238157838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b5f806108ad90505f600180836123ee919061407e565b7fe4e99eb92842190ab82eed325dd93d9ac79b581c2d3e63c7d8729e9263181cd961241991906141be565b61242391906136ef565b905081848261243291906141ee565b61243c91906141be565b92505050919050565b61244f8383612a61565b61246361245a6119a1565b5f858585611e45565b505050565b5f80612473846121e0565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146124b4576124b3818486612b54565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461253f576124f35f855f80612219565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146125be57600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f6126c183611351565b90505f60075f8481526020019081526020015f205490505f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050828214612760575f815f8581526020019081526020015f2054905080825f8581526020019081526020015f20819055508260075f8381526020019081526020015f2081905550505b60075f8581526020019081526020015f205f9055805f8481526020019081526020015f205f90555050505050565b5f60016008805490506127a1919061407e565b90505f60095f8481526020019081526020015f205490505f600883815481106127cd576127cc613adf565b5b905f5260205f200154905080600883815481106127ed576127ec613adf565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f905560088054806128355761283461422f565b5b600190038181905f5260205f20015f9055905550505050565b5f600161285a84611351565b612864919061407e565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b60605f8451036128f25760405180602001604052805f8152509050612a5a565b5f8261292357600360028651600461290a91906141ee565b61291491906136ef565b61291e919061418e565b61294a565b60036002865161293391906136ef565b61293d919061418e565b600461294991906141ee565b5b90505f8167ffffffffffffffff81111561296757612966613056565b5b6040519080825280601f01601f1916602001820160405280156129995781602001600182028036833780820191505090505b509050600185016020820187885189016020810180515f82525b82841015612a0e576003840193508351603f8160121c168701518653600186019550603f81600c1c168701518653600186019550603f8160061c168701518653600186019550603f81168701518653600186019550506129b3565b8082528915612a4e5760038c510660018114612a315760028114612a4457612a4c565b603d6001870353603d6002870353612a4c565b603d60018703535b505b50505050505080925050505b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612ad1575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612ac89190612f06565b60405180910390fd5b5f612add83835f611a78565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612b4f575f6040517f73c6ac6e000000000000000000000000000000000000000000000000000000008152600401612b469190612f06565b60405180910390fd5b505050565b612b5f838383612c17565b612c12575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612bd357806040517f7e273289000000000000000000000000000000000000000000000000000000008152600401612bca9190613035565b60405180910390fd5b81816040517f177e802f000000000000000000000000000000000000000000000000000000008152600401612c099291906139ca565b60405180910390fd5b505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612cce57508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612c8f5750612c8e84846116ef565b5b80612ccd57508273ffffffffffffffffffffffffffffffffffffffff16612cb583611968565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612d1c81612ce8565b8114612d26575f80fd5b50565b5f81359050612d3781612d13565b92915050565b5f60208284031215612d5257612d51612ce0565b5b5f612d5f84828501612d29565b91505092915050565b5f8115159050919050565b612d7c81612d68565b82525050565b5f602082019050612d955f830184612d73565b92915050565b5f819050919050565b612dad81612d9b565b8114612db7575f80fd5b50565b5f81359050612dc881612da4565b92915050565b5f8060408385031215612de457612de3612ce0565b5b5f612df185828601612dba565b9250506020612e0285828601612dba565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612e4e82612e0c565b612e588185612e16565b9350612e68818560208601612e26565b612e7181612e34565b840191505092915050565b5f6020820190508181035f830152612e948184612e44565b905092915050565b5f60208284031215612eb157612eb0612ce0565b5b5f612ebe84828501612dba565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612ef082612ec7565b9050919050565b612f0081612ee6565b82525050565b5f602082019050612f195f830184612ef7565b92915050565b612f2881612ee6565b8114612f32575f80fd5b50565b5f81359050612f4381612f1f565b92915050565b5f8060408385031215612f5f57612f5e612ce0565b5b5f612f6c85828601612f35565b9250506020612f7d85828601612dba565b9150509250929050565b5f60208284031215612f9c57612f9b612ce0565b5b5f612fa984828501612f35565b91505092915050565b5f819050919050565b5f612fd5612fd0612fcb84612ec7565b612fb2565b612ec7565b9050919050565b5f612fe682612fbb565b9050919050565b5f612ff782612fdc565b9050919050565b61300781612fed565b82525050565b5f6020820190506130205f830184612ffe565b92915050565b61302f81612d9b565b82525050565b5f6020820190506130485f830184613026565b92915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61308c82612e34565b810181811067ffffffffffffffff821117156130ab576130aa613056565b5b80604052505050565b5f6130bd612cd7565b90506130c98282613083565b919050565b5f67ffffffffffffffff8211156130e8576130e7613056565b5b6130f182612e34565b9050602081019050919050565b828183375f83830152505050565b5f61311e613119846130ce565b6130b4565b90508281526020810184848401111561313a57613139613052565b5b6131458482856130fe565b509392505050565b5f82601f8301126131615761316061304e565b5b813561317184826020860161310c565b91505092915050565b5f80604083850312156131905761318f612ce0565b5b5f61319d85828601612dba565b925050602083013567ffffffffffffffff8111156131be576131bd612ce4565b5b6131ca8582860161314d565b9150509250929050565b5f805f606084860312156131eb576131ea612ce0565b5b5f6131f886828701612f35565b935050602061320986828701612f35565b925050604061321a86828701612dba565b9150509250925092565b5f61322e82612fdc565b9050919050565b61323e81613224565b82525050565b5f6020820190506132575f830184613235565b92915050565b5f61326782612ee6565b9050919050565b6132778161325d565b8114613281575f80fd5b50565b5f813590506132928161326e565b92915050565b5f602082840312156132ad576132ac612ce0565b5b5f6132ba84828501613284565b91505092915050565b5f67ffffffffffffffff8211156132dd576132dc613056565b5b602082029050602081019050919050565b5f80fd5b5f6133046132ff846132c3565b6130b4565b90508083825260208201905060208402830185811115613327576133266132ee565b5b835b81811015613350578061333c8882612f35565b845260208401935050602081019050613329565b5050509392505050565b5f82601f83011261336e5761336d61304e565b5b813561337e8482602086016132f2565b91505092915050565b5f6020828403121561339c5761339b612ce0565b5b5f82013567ffffffffffffffff8111156133b9576133b8612ce4565b5b6133c58482850161335a565b91505092915050565b6133d781612d68565b81146133e1575f80fd5b50565b5f813590506133f2816133ce565b92915050565b5f806040838503121561340e5761340d612ce0565b5b5f61341b85828601612f35565b925050602061342c858286016133e4565b9150509250929050565b5f805f806080858703121561344e5761344d612ce0565b5b5f61345b87828801612f35565b945050602061346c87828801612f35565b935050604061347d87828801612dba565b925050606085013567ffffffffffffffff81111561349e5761349d612ce4565b5b6134aa8782880161314d565b91505092959194509250565b5f6134c082612ec7565b9050919050565b6134d0816134b6565b82525050565b5f6020820190506134e95f8301846134c7565b92915050565b5f806040838503121561350557613504612ce0565b5b5f61351285828601612f35565b925050602061352385828601612f35565b9150509250929050565b7f4f6e6c79204465706c6f7965722e0000000000000000000000000000000000005f82015250565b5f613561600e83612e16565b915061356c8261352d565b602082019050919050565b5f6020820190508181035f83015261358e81613555565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806135d957607f821691505b6020821081036135ec576135eb613595565b5b50919050565b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f613626601283612e16565b9150613631826135f2565b602082019050919050565b5f6020820190508181035f8301526136538161361a565b9050919050565b7f4d696e74696e67206e6f7420656e61626c6564000000000000000000000000005f82015250565b5f61368e601383612e16565b91506136998261365a565b602082019050919050565b5f6020820190508181035f8301526136bb81613682565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6136f982612d9b565b915061370483612d9b565b925082820190508082111561371c5761371b6136c2565b5b92915050565b7f45786365656473206d696e74206c696d697400000000000000000000000000005f82015250565b5f613756601283612e16565b915061376182613722565b602082019050919050565b5f6020820190508181035f8301526137838161374a565b9050919050565b5f60608201905061379d5f830186612ef7565b6137aa6020830185612ef7565b6137b76040830184613026565b949350505050565b5f815190506137cd816133ce565b92915050565b5f602082840312156137e8576137e7612ce0565b5b5f6137f5848285016137bf565b91505092915050565b7f5061796d656e74206661696c65640000000000000000000000000000000000005f82015250565b5f613832600e83612e16565b915061383d826137fe565b602082019050919050565b5f6020820190508181035f83015261385f81613826565b9050919050565b5f61387082612d9b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036138a2576138a16136c2565b5b600182019050919050565b7f4e6f7420746f6b656e206f776e657200000000000000000000000000000000005f82015250565b5f6138e1600f83612e16565b91506138ec826138ad565b602082019050919050565b5f6020820190508181035f83015261390e816138d5565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f61393982613915565b613943818561391f565b9350613953818560208601612e26565b61395c81612e34565b840191505092915050565b5f60408201905061397a5f830185613026565b818103602083015261398c818461392f565b90509392505050565b5f6060820190506139a85f830186612ef7565b6139b56020830185613026565b6139c26040830184612ef7565b949350505050565b5f6040820190506139dd5f830185612ef7565b6139ea6020830184613026565b9392505050565b7f496e76616c696420746f6b656e000000000000000000000000000000000000005f82015250565b5f613a25600d83612e16565b9150613a30826139f1565b602082019050919050565b5f6020820190508181035f830152613a5281613a19565b9050919050565b5f81519050613a6781612da4565b92915050565b5f60208284031215613a8257613a81612ce0565b5b5f613a8f84828501613a59565b91505092915050565b5f613aa282612fdc565b9050919050565b613ab281613a98565b82525050565b5f604082019050613acb5f830185613aa9565b613ad86020830184613026565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f546f6b656e20646f6573206e6f742065786973740000000000000000000000005f82015250565b5f613b40601483612e16565b9150613b4b82613b0c565b602082019050919050565b5f6020820190508181035f830152613b6d81613b34565b9050919050565b5f81905092915050565b7f68747470733a2f2f70392d72656e64657265722e76657263656c2e6170702f745f8201527f6f6b656e2f000000000000000000000000000000000000000000000000000000602082015250565b5f613bd8602583613b74565b9150613be382613b7e565b602582019050919050565b5f613bf882612e0c565b613c028185613b74565b9350613c12818560208601612e26565b80840191505092915050565b5f613c2882613bcc565b9150613c348284613bee565b915081905092915050565b5f67ffffffffffffffff821115613c5957613c58613056565b5b613c6282612e34565b9050602081019050919050565b5f613c81613c7c84613c3f565b6130b4565b905082815260208101848484011115613c9d57613c9c613052565b5b613ca8848285612e26565b509392505050565b5f82601f830112613cc457613cc361304e565b5b8151613cd4848260208601613c6f565b91505092915050565b5f60208284031215613cf257613cf1612ce0565b5b5f82015167ffffffffffffffff811115613d0f57613d0e612ce4565b5b613d1b84828501613cb0565b91505092915050565b7f7b226e616d65223a2250726f6a656374204e696e6520230000000000000000005f82015250565b5f613d58601783613b74565b9150613d6382613d24565b601782019050919050565b7f222c20226465736372697074696f6e223a2250726f6a6563742039202d2073615f8201527f76696e6720656e64616e67657265642063726561747572657320696e20756e6360208201527f686172746564207265616c6d732e222c00000000000000000000000000000000604082015250565b5f613dee605083613b74565b9150613df982613d6e565b605082019050919050565b7f22696d616765223a2200000000000000000000000000000000000000000000005f82015250565b5f613e38600983613b74565b9150613e4382613e04565b600982019050919050565b7f222c202265787465726e616c5f75726c223a22000000000000000000000000005f82015250565b5f613e82601383613b74565b9150613e8d82613e4e565b601382019050919050565b7f222c202261747472696275746573223a000000000000000000000000000000005f82015250565b5f613ecc601083613b74565b9150613ed782613e98565b601082019050919050565b7f7d000000000000000000000000000000000000000000000000000000000000005f82015250565b5f613f16600183613b74565b9150613f2182613ee2565b600182019050919050565b5f613f3682613d4c565b9150613f428287613bee565b9150613f4d82613de2565b9150613f5882613e2c565b9150613f648286613bee565b9150613f6f82613e76565b9150613f7b8285613bee565b9150613f8682613ec0565b9150613f928284613bee565b9150613f9d82613f0a565b915081905095945050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f613fdf601d83613b74565b9150613fea82613fab565b601d82019050919050565b5f613fff82613fd3565b915061400b8284613bee565b915081905092915050565b7f416c6c206d696e746564000000000000000000000000000000000000000000005f82015250565b5f61404a600a83612e16565b915061405582614016565b602082019050919050565b5f6020820190508181035f8301526140778161403e565b9050919050565b5f61408882612d9b565b915061409383612d9b565b92508282039050818111156140ab576140aa6136c2565b5b92915050565b5f6140bb82612d9b565b91505f82036140cd576140cc6136c2565b5b600182039050919050565b5f6080820190506140eb5f830187612ef7565b6140f86020830186612ef7565b6141056040830185613026565b8181036060830152614117818461392f565b905095945050505050565b5f8151905061413081612d13565b92915050565b5f6020828403121561414b5761414a612ce0565b5b5f61415884828501614122565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61419882612d9b565b91506141a383612d9b565b9250826141b3576141b2614161565b5b828204905092915050565b5f6141c882612d9b565b91506141d383612d9b565b9250826141e3576141e2614161565b5b828206905092915050565b5f6141f882612d9b565b915061420383612d9b565b925082820261421181612d9b565b91508282048414831517614228576142276136c2565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220fd85b315a71bafd2ff8a13d5164a8c7845d126c1a3062671ef896ad55d97ac4c64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000200f5dbe0e50c8d21d035983bf444f86c5908ea000000000000000000000000b931e339b4f5eb3d4d039ce1451426754063c711
-----Decoded View---------------
Arg [0] : dataContractAddress (address): 0x0200F5DBe0E50C8d21D035983Bf444f86c5908EA
Arg [1] : _deployer (address): 0xb931E339b4f5eB3D4D039CE1451426754063C711
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000200f5dbe0e50c8d21d035983bf444f86c5908ea
Arg [1] : 000000000000000000000000b931e339b4f5eb3d4d039ce1451426754063c711
Deployed Bytecode Sourcemap
151567:5008:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;125682:224;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152744:158;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;108762:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109934:158;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109753:115;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;153123:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151627:35;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;153251:710;;;:::i;:::-;;126326:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;155408:214;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;110603:588;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125990:260;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152021:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151669:42;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;111262:134;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;156372:200;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;126507:231;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151926:45;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151772:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152085:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108575:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152910:205;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;152054:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152610:123;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;108300:213;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;134112:103;;;:::i;:::-;;151718:47;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;133437:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108922:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110164:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111467:236;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;154226:1174;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151803:31;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110381:155;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;134370:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125682:224;125784:4;125823:35;125808:50;;;:11;:50;;;;:90;;;;125862:36;125886:11;125862:23;:36::i;:::-;125808:90;125801:97;;125682:224;;;:::o;152744:158::-;152555:8;;;;;;;;;;;152541:22;;:10;:22;;;152533:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;152849:10:::1;152837:9;:22;;;;152883:11;152870:10;:24;;;;152744:158:::0;;:::o;108762:91::-;108807:13;108840:5;108833:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108762:91;:::o;109934:158::-;110001:7;110021:22;110035:7;110021:13;:22::i;:::-;;110063:21;110076:7;110063:12;:21::i;:::-;110056:28;;109934:158;;;:::o;109753:115::-;109825:35;109834:2;109838:7;109847:12;:10;:12::i;:::-;109825:8;:35::i;:::-;109753:115;;:::o;153123:120::-;153188:4;153212:10;:23;153223:11;153212:23;;;;;;;;;;;;;;;;;;;;;;;;;153205:30;;153123:120;;;:::o;151627:35::-;;;;;;;;;;;;;:::o;153251:710::-;153311:10;153295:13;:11;:13::i;:::-;:26;153287:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;153375:1;153363:9;;:13;153355:45;;;;;;;;;;;;:::i;:::-;;;;;;;;;153451:18;151764:1;153451:40;;153506:25;153520:10;153506:13;:25::i;:::-;153502:73;;;153562:1;153548:15;;;;;:::i;:::-;;;153502:73;153618:10;153593;:22;153604:10;153593:22;;;;;;;;;;;;;;;;:35;153585:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;153722:12;;;;;;;;;;;:25;;;153748:10;153768:4;153775:9;;153722:63;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;153700:127;;;;;;;;;;;;:::i;:::-;;;;;;;;;153840:15;153858:19;:17;:19::i;:::-;153840:37;;153888:30;153898:10;153910:7;153888:9;:30::i;:::-;153929:10;:22;153940:10;153929:22;;;;;;;;;;;;;;;;:24;;;;;;;;;:::i;:::-;;;;;;153276:685;;153251:710::o;126326:104::-;126378:7;126405:10;:17;;;;126398:24;;126326:104;:::o;155408:214::-;155525:10;155505:30;;:16;155513:7;155505;:16::i;:::-;:30;;;155497:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;155566:12;;;;;;;;;;;:25;;;155592:7;155601:12;155566:48;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;155408:214;;:::o;110603:588::-;110712:1;110698:16;;:2;:16;;;110694:89;;110768:1;110738:33;;;;;;;;;;;:::i;:::-;;;;;;;;110694:89;111004:21;111028:34;111036:2;111040:7;111049:12;:10;:12::i;:::-;111028:7;:34::i;:::-;111004:58;;111094:4;111077:21;;:13;:21;;;111073:111;;111143:4;111149:7;111158:13;111122:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;111073:111;110683:508;110603:588;;;:::o;125990:260::-;126078:7;126111:16;126121:5;126111:9;:16::i;:::-;126102:5;:25;126098:101;;126174:5;126181;126151:36;;;;;;;;;;;;:::i;:::-;;;;;;;;126098:101;126216:12;:19;126229:5;126216:19;;;;;;;;;;;;;;;:26;126236:5;126216:26;;;;;;;;;;;;126209:33;;125990:260;;;;:::o;152021:26::-;;;;;;;;;;;;;:::o;151669:42::-;;;:::o;111262:134::-;111349:39;111366:4;111372:2;111376:7;111349:39;;;;;;;;;;;;:16;:39::i;:::-;111262:134;;;:::o;156372:200::-;152555:8;;;;;;;;;;;152541:22;;:10;:22;;;152533:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;156477:1:::1;156451:28;;156459:5;156451:28;;::::0;156443:54:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;156508:5;:14;;;156523:8;;;;;;;;;;;156533:5;:15;;;156557:4;156533:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;156508:56;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;156372:200:::0;:::o;126507:231::-;126573:7;126606:13;:11;:13::i;:::-;126597:5;:22;126593:103;;126674:1;126678:5;126643:41;;;;;;;;;;;;:::i;:::-;;;;;;;;126593:103;126713:10;126724:5;126713:17;;;;;;;;:::i;:::-;;;;;;;;;;126706:24;;126507:231;;;:::o;151926:45::-;;;;;;;;;;;;;;;;;:::o;151772:24::-;;;;:::o;152085:25::-;;;;:::o;108575:120::-;108638:7;108665:22;108679:7;108665:13;:22::i;:::-;108658:29;;108575:120;;;:::o;152910:205::-;152555:8;;;;;;;;;;;152541:22;;:10;:22;;;152533:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;153002:9:::1;152997:111;153021:12;:19;153017:1;:23;152997:111;;;153092:4;153062:10;:27;153073:12;153086:1;153073:15;;;;;;;;:::i;:::-;;;;;;;;153062:27;;;;;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;153042:3;;;;;;;152997:111;;;;152910:205:::0;:::o;152054:24::-;;;;:::o;152610:123::-;152555:8;;;;;;;;;;;152541:22;;:10;:22;;;152533:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;152712:12:::1;152690;;:35;;;;;;;;;;;;;;;;;;152610:123:::0;:::o;108300:213::-;108363:7;108404:1;108387:19;;:5;:19;;;108383:89;;108457:1;108430:30;;;;;;;;;;;:::i;:::-;;;;;;;;108383:89;108489:9;:16;108499:5;108489:16;;;;;;;;;;;;;;;;108482:23;;108300:213;;;:::o;134112:103::-;133323:13;:11;:13::i;:::-;134177:30:::1;134204:1;134177:18;:30::i;:::-;134112:103::o:0;151718:47::-;151764:1;151718:47;:::o;133437:87::-;133483:7;133510:6;;;;;;;;;;;133503:13;;133437:87;:::o;108922:95::-;108969:13;109002:7;108995:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108922:95;:::o;110164:146::-;110250:52;110269:12;:10;:12::i;:::-;110283:8;110293;110250:18;:52::i;:::-;110164:146;;:::o;111467:236::-;111581:31;111594:4;111600:2;111604:7;111581:12;:31::i;:::-;111623:72;111657:12;:10;:12::i;:::-;111671:4;111677:2;111681:7;111690:4;111623:33;:72::i;:::-;111467:236;;;;:::o;154226:1174::-;154291:13;154331:10;154321:7;:20;154313:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;154440:22;154530:17;154539:7;154530:8;:17::i;:::-;154472:76;;;;;;;;:::i;:::-;;;;;;;;;;;;;154440:109;;154556:25;154649:17;154658:7;154649:8;:17::i;:::-;154591:76;;;;;;;;:::i;:::-;;;;;;;;;;;;;154556:112;;154675:20;154698:12;;;;;;;;;;;:22;;;154721:7;154698:31;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154675:54;;154839:535;154969:17;154978:7;154969:8;:17::i;:::-;155135:8;155220:11;155306:6;154899:441;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;154839:13;:535::i;:::-;154762:623;;;;;;;;:::i;:::-;;;;;;;;;;;;;154738:654;;;;;154226:1174;;;:::o;151803:31::-;;;;;;;;;;;;;:::o;110381:155::-;110469:4;110493:18;:25;110512:5;110493:25;;;;;;;;;;;;;;;:35;110519:8;110493:35;;;;;;;;;;;;;;;;;;;;;;;;;110486:42;;110381:155;;;;:::o;134370:220::-;133323:13;:11;:13::i;:::-;134475:1:::1;134455:22;;:8;:22;;::::0;134451:93:::1;;134529:1;134501:31;;;;;;;;;;;:::i;:::-;;;;;;;;134451:93;134554:28;134573:8;134554:18;:28::i;:::-;134370:220:::0;:::o;107931:305::-;108033:4;108085:25;108070:40;;;:11;:40;;;;:105;;;;108142:33;108127:48;;;:11;:48;;;;108070:105;:158;;;;108192:36;108216:11;108192:23;:36::i;:::-;108070:158;108050:178;;107931:305;;;:::o;122985:247::-;123048:7;123068:13;123084:17;123093:7;123084:8;:17::i;:::-;123068:33;;123133:1;123116:19;;:5;:19;;;123112:90;;123182:7;123159:31;;;;;;;;;;;:::i;:::-;;;;;;;;123112:90;123219:5;123212:12;;;122985:247;;;:::o;112466:129::-;112536:7;112563:15;:24;112579:7;112563:24;;;;;;;;;;;;;;;;;;;;;112556:31;;112466:129;;;:::o;18450:98::-;18503:7;18530:10;18523:17;;18450:98;:::o;121217:122::-;121298:33;121307:2;121311:7;121320:4;121326;121298:8;:33::i;:::-;121217:122;;;:::o;153969:250::-;154015:7;154055:1;154043:9;;:13;154035:36;;;;;;;;;;;;:::i;:::-;;;;;;;;;154082:13;154111:9;;154098:10;:22;;;;:::i;:::-;154082:38;;154131:15;154149;154158:5;154149:8;:15::i;:::-;154131:33;;154175:9;;:11;;;;;;;;;:::i;:::-;;;;;;154204:7;154197:14;;;;153969:250;:::o;117285:102::-;117353:26;117363:2;117367:7;117353:26;;;;;;;;;;;;:9;:26::i;:::-;117285:102;;:::o;126799:640::-;126894:7;126914:21;126938:32;126952:2;126956:7;126965:4;126938:13;:32::i;:::-;126914:56;;127012:1;126987:27;;:13;:27;;;126983:214;;127031:40;127063:7;127031:31;:40::i;:::-;126983:214;;;127110:2;127093:19;;:13;:19;;;127089:108;;127129:56;127162:13;127177:7;127129:32;:56::i;:::-;127089:108;126983:214;127225:1;127211:16;;:2;:16;;;127207:192;;127244:45;127281:7;127244:36;:45::i;:::-;127207:192;;;127328:2;127311:19;;:13;:19;;;127307:92;;127347:40;127375:2;127379:7;127347:27;:40::i;:::-;127307:92;127207:192;127418:13;127411:20;;;126799:640;;;;;:::o;133602:166::-;133673:12;:10;:12::i;:::-;133662:23;;:7;:5;:7::i;:::-;:23;;;133658:103;;133736:12;:10;:12::i;:::-;133709:40;;;;;;;;;;;:::i;:::-;;;;;;;;133658:103;133602:166::o;134750:191::-;134824:16;134843:6;;;;;;;;;;;134824:25;;134869:8;134860:6;;:17;;;;;;;;;;;;;;;;;;134924:8;134893:40;;134914:8;134893:40;;;;;;;;;;;;134813:128;134750:191;:::o;122424:318::-;122552:1;122532:22;;:8;:22;;;122528:93;;122600:8;122578:31;;;;;;;;;;;:::i;:::-;;;;;;;;122528:93;122669:8;122631:18;:25;122650:5;122631:25;;;;;;;;;;;;;;;:35;122657:8;122631:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;122715:8;122693:41;;122708:5;122693:41;;;122725:8;122693:41;;;;;;:::i;:::-;;;;;;;;122424:318;;;:::o;16800:948::-;17004:1;16987:2;:14;;;:18;16983:758;;;17042:2;17026:36;;;17063:8;17073:4;17079:7;17088:4;17026:67;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;17022:708;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17406:1;17389:6;:13;:18;17385:330;;17531:2;17495:39;;;;;;;;;;;:::i;:::-;;;;;;;;17385:330;17665:6;17659:13;17650:6;17646:2;17642:15;17635:38;17022:708;17151:41;;;17141:51;;;:6;:51;;;;17137:185;;17299:2;17263:39;;;;;;;;;;;:::i;:::-;;;;;;;;17137:185;17094:243;16983:758;16800:948;;;;;:::o;155826:506::-;155882:13;155921:1;155912:5;:10;155908:26;;155924:10;;;;;;;;;;;;;;;;;;;;;155908:26;155945:12;155960:5;155945:20;;155976:14;156001:78;156016:1;156008:4;:9;156001:78;;156034:8;;;;;:::i;:::-;;;;156065:2;156057:10;;;;;:::i;:::-;;;156001:78;;;156089:19;156121:6;156111:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;156089:39;;156139:154;156155:1;156146:5;:10;156139:154;;156183:1;156173:11;;;;;:::i;:::-;;;156250:2;156242:5;:10;;;;:::i;:::-;156229:2;:24;;;;:::i;:::-;156216:39;;156199:6;156206;156199:14;;;;;;;;:::i;:::-;;;;;:56;;;;;;;;;;;156279:2;156270:11;;;;;:::i;:::-;;;156139:154;;;156317:6;156303:21;;;;;155826:506;;;;:::o;135652:126::-;135710:13;135743:27;135751:4;135757:6;;;;;;;;;;;;;;;;;135765:4;135743:7;:27::i;:::-;135736:34;;135652:126;;;:::o;106529:148::-;106605:4;106644:25;106629:40;;;:11;:40;;;;106622:47;;106529:148;;;:::o;112228:117::-;112294:7;112321;:16;112329:7;112321:16;;;;;;;;;;;;;;;;;;;;;112314:23;;112228:117;;;:::o;121527:678::-;121689:9;:31;;;;121718:1;121702:18;;:4;:18;;;;121689:31;121685:471;;;121737:13;121753:22;121767:7;121753:13;:22::i;:::-;121737:38;;121922:1;121906:18;;:4;:18;;;;:35;;;;;121937:4;121928:13;;:5;:13;;;;121906:35;:69;;;;;121946:29;121963:5;121970:4;121946:16;:29::i;:::-;121945:30;121906:69;121902:144;;;122025:4;122003:27;;;;;;;;;;;:::i;:::-;;;;;;;;121902:144;122066:9;122062:83;;;122121:7;122117:2;122101:28;;122110:5;122101:28;;;;;;;;;;;;122062:83;121722:434;121685:471;122195:2;122168:15;:24;122184:7;122168:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;121527:678;;;;:::o;155630:188::-;155686:7;155706:13;155722:4;155706:20;;155737:9;155772:1;155766;155758:5;:9;;;;:::i;:::-;155750:4;:18;;;;:::i;:::-;155749:24;;;;:::i;:::-;155737:36;;155805:5;155796;155792:1;:9;;;;:::i;:::-;155791:19;;;;:::i;:::-;155784:26;;;;155630:188;;;:::o;117614:210::-;117709:18;117715:2;117719:7;117709:5;:18::i;:::-;117738:78;117772:12;:10;:12::i;:::-;117794:1;117798:2;117802:7;117811:4;117738:33;:78::i;:::-;117614:210;;;:::o;115427:824::-;115513:7;115533:12;115548:17;115557:7;115548:8;:17::i;:::-;115533:32;;115644:1;115628:18;;:4;:18;;;115624:88;;115663:37;115680:4;115686;115692:7;115663:16;:37::i;:::-;115624:88;115775:1;115759:18;;:4;:18;;;115755:263;;115877:48;115894:1;115898:7;115915:1;115919:5;115877:8;:48::i;:::-;115990:1;115971:9;:15;115981:4;115971:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;115755:263;116048:1;116034:16;;:2;:16;;;116030:111;;116113:1;116096:9;:13;116106:2;116096:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;116030:111;116172:2;116153:7;:16;116161:7;116153:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;116211:7;116207:2;116192:27;;116201:4;116192:27;;;;;;;;;;;;116239:4;116232:11;;;115427:824;;;;;:::o;128159:164::-;128263:10;:17;;;;128236:15;:24;128252:7;128236:24;;;;;;;;;;;:44;;;;128291:10;128307:7;128291:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;128159:164;:::o;128950:1075::-;129216:22;129241:15;129251:4;129241:9;:15::i;:::-;129216:40;;129267:18;129288:17;:26;129306:7;129288:26;;;;;;;;;;;;129267:47;;129327:61;129391:12;:18;129404:4;129391:18;;;;;;;;;;;;;;;129327:82;;129530:14;129516:10;:28;129512:330;;129561:19;129583;:35;129603:14;129583:35;;;;;;;;;;;;129561:57;;129669:11;129635:19;:31;129655:10;129635:31;;;;;;;;;;;:45;;;;129786:10;129753:17;:30;129771:11;129753:30;;;;;;;;;;;:43;;;;129546:296;129512:330;129938:17;:26;129956:7;129938:26;;;;;;;;;;;129931:33;;;129982:19;:35;130002:14;129982:35;;;;;;;;;;;129975:42;;;129031:994;;;128950:1075;;:::o;130320:1079::-;130573:22;130618:1;130598:10;:17;;;;:21;;;;:::i;:::-;130573:46;;130630:18;130651:15;:24;130667:7;130651:24;;;;;;;;;;;;130630:45;;131002:19;131024:10;131035:14;131024:26;;;;;;;;:::i;:::-;;;;;;;;;;131002:48;;131088:11;131063:10;131074;131063:22;;;;;;;;:::i;:::-;;;;;;;;;:36;;;;131199:10;131168:15;:28;131184:11;131168:28;;;;;;;;;;;:41;;;;131340:15;:24;131356:7;131340:24;;;;;;;;;;;131333:31;;;131375:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;130391:1008;;;130320:1079;:::o;127740:218::-;127825:14;127858:1;127842:13;127852:2;127842:9;:13::i;:::-;:17;;;;:::i;:::-;127825:34;;127897:7;127870:12;:16;127883:2;127870:16;;;;;;;;;;;;;;;:24;127887:6;127870:24;;;;;;;;;;;:34;;;;127944:6;127915:17;:26;127933:7;127915:26;;;;;;;;;;;:35;;;;127814:144;127740:218;;:::o;136190:4109::-;136287:13;136539:1;136524:4;:11;:16;136520:31;;136542:9;;;;;;;;;;;;;;;;136520:31;137504:20;137527:11;:69;;137595:1;137590;137576:4;:11;137572:1;:15;;;;:::i;:::-;:19;;;;:::i;:::-;137571:25;;;;:::i;:::-;137527:69;;;137566:1;137561;137547:4;:11;:15;;;;:::i;:::-;137546:21;;;;:::i;:::-;137541:1;:27;;;;:::i;:::-;137527:69;137504:92;;137609:20;137643:12;137632:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;137609:47;;137808:1;137801:5;137797:13;137912:4;137904:6;137900:17;137946:4;137994;137988:11;137982:4;137978:22;138246:4;138238:6;138234:17;138289:8;138283:15;138329:4;138319:8;138312:22;138404:1286;138439:6;138430:7;138427:19;138404:1286;;;138545:1;138536:7;138532:15;138521:26;;138584:7;138578:14;139180:4;139172:5;139168:2;139164:14;139160:25;139150:8;139146:40;139140:47;139129:9;139121:67;139234:1;139223:9;139219:17;139206:30;;139326:4;139318:5;139314:2;139310:14;139306:25;139296:8;139292:40;139286:47;139275:9;139267:67;139380:1;139369:9;139365:17;139352:30;;139471:4;139463:5;139460:1;139456:13;139452:24;139442:8;139438:39;139432:46;139421:9;139413:66;139525:1;139514:9;139510:17;139497:30;;139608:4;139601:5;139597:16;139587:8;139583:31;139577:38;139566:9;139558:58;139662:1;139651:9;139647:17;139634:30;;138466:1224;138404:1286;;;139771:10;139761:8;139754:28;139801:11;139798:457;;;139986:1;139979:4;139973:11;139969:19;140011:1;140006:135;;;;140164:1;140159:81;;;;139962:278;;140006:135;140063:4;140059:1;140048:9;140044:17;140036:32;140117:4;140113:1;140102:9;140098:17;140090:32;140006:135;;140159:81;140216:4;140212:1;140201:9;140197:17;140189:32;139962:278;;139798:457;137694:2572;;;;;;140285:6;140278:13;;;;136190:4109;;;;;;:::o;116587:335::-;116669:1;116655:16;;:2;:16;;;116651:89;;116725:1;116695:33;;;;;;;;;;;:::i;:::-;;;;;;;;116651:89;116750:21;116774:32;116782:2;116786:7;116803:1;116774:7;:32::i;:::-;116750:56;;116846:1;116821:27;;:13;:27;;;116817:98;;116900:1;116872:31;;;;;;;;;;;:::i;:::-;;;;;;;;116817:98;116640:282;116587:335;;:::o;113634:376::-;113747:38;113761:5;113768:7;113777;113747:13;:38::i;:::-;113742:261;;113823:1;113806:19;;:5;:19;;;113802:190;;113876:7;113853:31;;;;;;;;;;;:::i;:::-;;;;;;;;113802:190;113959:7;113968;113932:44;;;;;;;;;;;;:::i;:::-;;;;;;;;113742:261;113634:376;;;:::o;112915:276::-;113018:4;113074:1;113055:21;;:7;:21;;;;:128;;;;;113103:7;113094:16;;:5;:16;;;:52;;;;113114:32;113131:5;113138:7;113114:16;:32::i;:::-;113094:52;:88;;;;113175:7;113150:32;;:21;113163:7;113150:12;:21::i;:::-;:32;;;113094:88;113055:128;113035:148;;112915:276;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:77::-;1555:7;1584:5;1573:16;;1518:77;;;:::o;1601:122::-;1674:24;1692:5;1674:24;:::i;:::-;1667:5;1664:35;1654:63;;1713:1;1710;1703:12;1654:63;1601:122;:::o;1729:139::-;1775:5;1813:6;1800:20;1791:29;;1829:33;1856:5;1829:33;:::i;:::-;1729:139;;;;:::o;1874:474::-;1942:6;1950;1999:2;1987:9;1978:7;1974:23;1970:32;1967:119;;;2005:79;;:::i;:::-;1967:119;2125:1;2150:53;2195:7;2186:6;2175:9;2171:22;2150:53;:::i;:::-;2140:63;;2096:117;2252:2;2278:53;2323:7;2314:6;2303:9;2299:22;2278:53;:::i;:::-;2268:63;;2223:118;1874:474;;;;;:::o;2354:99::-;2406:6;2440:5;2434:12;2424:22;;2354:99;;;:::o;2459:169::-;2543:11;2577:6;2572:3;2565:19;2617:4;2612:3;2608:14;2593:29;;2459:169;;;;:::o;2634:139::-;2723:6;2718:3;2713;2707:23;2764:1;2755:6;2750:3;2746:16;2739:27;2634:139;;;:::o;2779:102::-;2820:6;2871:2;2867:7;2862:2;2855:5;2851:14;2847:28;2837:38;;2779:102;;;:::o;2887:377::-;2975:3;3003:39;3036:5;3003:39;:::i;:::-;3058:71;3122:6;3117:3;3058:71;:::i;:::-;3051:78;;3138:65;3196:6;3191:3;3184:4;3177:5;3173:16;3138:65;:::i;:::-;3228:29;3250:6;3228:29;:::i;:::-;3223:3;3219:39;3212:46;;2979:285;2887:377;;;;:::o;3270:313::-;3383:4;3421:2;3410:9;3406:18;3398:26;;3470:9;3464:4;3460:20;3456:1;3445:9;3441:17;3434:47;3498:78;3571:4;3562:6;3498:78;:::i;:::-;3490:86;;3270:313;;;;:::o;3589:329::-;3648:6;3697:2;3685:9;3676:7;3672:23;3668:32;3665:119;;;3703:79;;:::i;:::-;3665:119;3823:1;3848:53;3893:7;3884:6;3873:9;3869:22;3848:53;:::i;:::-;3838:63;;3794:117;3589:329;;;;:::o;3924:126::-;3961:7;4001:42;3994:5;3990:54;3979:65;;3924:126;;;:::o;4056:96::-;4093:7;4122:24;4140:5;4122:24;:::i;:::-;4111:35;;4056:96;;;:::o;4158:118::-;4245:24;4263:5;4245:24;:::i;:::-;4240:3;4233:37;4158:118;;:::o;4282:222::-;4375:4;4413:2;4402:9;4398:18;4390:26;;4426:71;4494:1;4483:9;4479:17;4470:6;4426:71;:::i;:::-;4282:222;;;;:::o;4510:122::-;4583:24;4601:5;4583:24;:::i;:::-;4576:5;4573:35;4563:63;;4622:1;4619;4612:12;4563:63;4510:122;:::o;4638:139::-;4684:5;4722:6;4709:20;4700:29;;4738:33;4765:5;4738:33;:::i;:::-;4638:139;;;;:::o;4783:474::-;4851:6;4859;4908:2;4896:9;4887:7;4883:23;4879:32;4876:119;;;4914:79;;:::i;:::-;4876:119;5034:1;5059:53;5104:7;5095:6;5084:9;5080:22;5059:53;:::i;:::-;5049:63;;5005:117;5161:2;5187:53;5232:7;5223:6;5212:9;5208:22;5187:53;:::i;:::-;5177:63;;5132:118;4783:474;;;;;:::o;5263:329::-;5322:6;5371:2;5359:9;5350:7;5346:23;5342:32;5339:119;;;5377:79;;:::i;:::-;5339:119;5497:1;5522:53;5567:7;5558:6;5547:9;5543:22;5522:53;:::i;:::-;5512:63;;5468:117;5263:329;;;;:::o;5598:60::-;5626:3;5647:5;5640:12;;5598:60;;;:::o;5664:142::-;5714:9;5747:53;5765:34;5774:24;5792:5;5774:24;:::i;:::-;5765:34;:::i;:::-;5747:53;:::i;:::-;5734:66;;5664:142;;;:::o;5812:126::-;5862:9;5895:37;5926:5;5895:37;:::i;:::-;5882:50;;5812:126;;;:::o;5944:150::-;6018:9;6051:37;6082:5;6051:37;:::i;:::-;6038:50;;5944:150;;;:::o;6100:179::-;6211:61;6266:5;6211:61;:::i;:::-;6206:3;6199:74;6100:179;;:::o;6285:270::-;6402:4;6440:2;6429:9;6425:18;6417:26;;6453:95;6545:1;6534:9;6530:17;6521:6;6453:95;:::i;:::-;6285:270;;;;:::o;6561:118::-;6648:24;6666:5;6648:24;:::i;:::-;6643:3;6636:37;6561:118;;:::o;6685:222::-;6778:4;6816:2;6805:9;6801:18;6793:26;;6829:71;6897:1;6886:9;6882:17;6873:6;6829:71;:::i;:::-;6685:222;;;;:::o;6913:117::-;7022:1;7019;7012:12;7036:117;7145:1;7142;7135:12;7159:180;7207:77;7204:1;7197:88;7304:4;7301:1;7294:15;7328:4;7325:1;7318:15;7345:281;7428:27;7450:4;7428:27;:::i;:::-;7420:6;7416:40;7558:6;7546:10;7543:22;7522:18;7510:10;7507:34;7504:62;7501:88;;;7569:18;;:::i;:::-;7501:88;7609:10;7605:2;7598:22;7388:238;7345:281;;:::o;7632:129::-;7666:6;7693:20;;:::i;:::-;7683:30;;7722:33;7750:4;7742:6;7722:33;:::i;:::-;7632:129;;;:::o;7767:307::-;7828:4;7918:18;7910:6;7907:30;7904:56;;;7940:18;;:::i;:::-;7904:56;7978:29;8000:6;7978:29;:::i;:::-;7970:37;;8062:4;8056;8052:15;8044:23;;7767:307;;;:::o;8080:148::-;8178:6;8173:3;8168;8155:30;8219:1;8210:6;8205:3;8201:16;8194:27;8080:148;;;:::o;8234:423::-;8311:5;8336:65;8352:48;8393:6;8352:48;:::i;:::-;8336:65;:::i;:::-;8327:74;;8424:6;8417:5;8410:21;8462:4;8455:5;8451:16;8500:3;8491:6;8486:3;8482:16;8479:25;8476:112;;;8507:79;;:::i;:::-;8476:112;8597:54;8644:6;8639:3;8634;8597:54;:::i;:::-;8317:340;8234:423;;;;;:::o;8676:338::-;8731:5;8780:3;8773:4;8765:6;8761:17;8757:27;8747:122;;8788:79;;:::i;:::-;8747:122;8905:6;8892:20;8930:78;9004:3;8996:6;8989:4;8981:6;8977:17;8930:78;:::i;:::-;8921:87;;8737:277;8676:338;;;;:::o;9020:652::-;9097:6;9105;9154:2;9142:9;9133:7;9129:23;9125:32;9122:119;;;9160:79;;:::i;:::-;9122:119;9280:1;9305:53;9350:7;9341:6;9330:9;9326:22;9305:53;:::i;:::-;9295:63;;9251:117;9435:2;9424:9;9420:18;9407:32;9466:18;9458:6;9455:30;9452:117;;;9488:79;;:::i;:::-;9452:117;9593:62;9647:7;9638:6;9627:9;9623:22;9593:62;:::i;:::-;9583:72;;9378:287;9020:652;;;;;:::o;9678:619::-;9755:6;9763;9771;9820:2;9808:9;9799:7;9795:23;9791:32;9788:119;;;9826:79;;:::i;:::-;9788:119;9946:1;9971:53;10016:7;10007:6;9996:9;9992:22;9971:53;:::i;:::-;9961:63;;9917:117;10073:2;10099:53;10144:7;10135:6;10124:9;10120:22;10099:53;:::i;:::-;10089:63;;10044:118;10201:2;10227:53;10272:7;10263:6;10252:9;10248:22;10227:53;:::i;:::-;10217:63;;10172:118;9678:619;;;;;:::o;10303:141::-;10368:9;10401:37;10432:5;10401:37;:::i;:::-;10388:50;;10303:141;;;:::o;10450:161::-;10552:52;10598:5;10552:52;:::i;:::-;10547:3;10540:65;10450:161;;:::o;10617:252::-;10725:4;10763:2;10752:9;10748:18;10740:26;;10776:86;10859:1;10848:9;10844:17;10835:6;10776:86;:::i;:::-;10617:252;;;;:::o;10875:111::-;10927:7;10956:24;10974:5;10956:24;:::i;:::-;10945:35;;10875:111;;;:::o;10992:152::-;11080:39;11113:5;11080:39;:::i;:::-;11073:5;11070:50;11060:78;;11134:1;11131;11124:12;11060:78;10992:152;:::o;11150:169::-;11211:5;11249:6;11236:20;11227:29;;11265:48;11307:5;11265:48;:::i;:::-;11150:169;;;;:::o;11325:359::-;11399:6;11448:2;11436:9;11427:7;11423:23;11419:32;11416:119;;;11454:79;;:::i;:::-;11416:119;11574:1;11599:68;11659:7;11650:6;11639:9;11635:22;11599:68;:::i;:::-;11589:78;;11545:132;11325:359;;;;:::o;11690:311::-;11767:4;11857:18;11849:6;11846:30;11843:56;;;11879:18;;:::i;:::-;11843:56;11929:4;11921:6;11917:17;11909:25;;11989:4;11983;11979:15;11971:23;;11690:311;;;:::o;12007:117::-;12116:1;12113;12106:12;12147:710;12243:5;12268:81;12284:64;12341:6;12284:64;:::i;:::-;12268:81;:::i;:::-;12259:90;;12369:5;12398:6;12391:5;12384:21;12432:4;12425:5;12421:16;12414:23;;12485:4;12477:6;12473:17;12465:6;12461:30;12514:3;12506:6;12503:15;12500:122;;;12533:79;;:::i;:::-;12500:122;12648:6;12631:220;12665:6;12660:3;12657:15;12631:220;;;12740:3;12769:37;12802:3;12790:10;12769:37;:::i;:::-;12764:3;12757:50;12836:4;12831:3;12827:14;12820:21;;12707:144;12691:4;12686:3;12682:14;12675:21;;12631:220;;;12635:21;12249:608;;12147:710;;;;;:::o;12880:370::-;12951:5;13000:3;12993:4;12985:6;12981:17;12977:27;12967:122;;13008:79;;:::i;:::-;12967:122;13125:6;13112:20;13150:94;13240:3;13232:6;13225:4;13217:6;13213:17;13150:94;:::i;:::-;13141:103;;12957:293;12880:370;;;;:::o;13256:539::-;13340:6;13389:2;13377:9;13368:7;13364:23;13360:32;13357:119;;;13395:79;;:::i;:::-;13357:119;13543:1;13532:9;13528:17;13515:31;13573:18;13565:6;13562:30;13559:117;;;13595:79;;:::i;:::-;13559:117;13700:78;13770:7;13761:6;13750:9;13746:22;13700:78;:::i;:::-;13690:88;;13486:302;13256:539;;;;:::o;13801:116::-;13871:21;13886:5;13871:21;:::i;:::-;13864:5;13861:32;13851:60;;13907:1;13904;13897:12;13851:60;13801:116;:::o;13923:133::-;13966:5;14004:6;13991:20;13982:29;;14020:30;14044:5;14020:30;:::i;:::-;13923:133;;;;:::o;14062:468::-;14127:6;14135;14184:2;14172:9;14163:7;14159:23;14155:32;14152:119;;;14190:79;;:::i;:::-;14152:119;14310:1;14335:53;14380:7;14371:6;14360:9;14356:22;14335:53;:::i;:::-;14325:63;;14281:117;14437:2;14463:50;14505:7;14496:6;14485:9;14481:22;14463:50;:::i;:::-;14453:60;;14408:115;14062:468;;;;;:::o;14536:943::-;14631:6;14639;14647;14655;14704:3;14692:9;14683:7;14679:23;14675:33;14672:120;;;14711:79;;:::i;:::-;14672:120;14831:1;14856:53;14901:7;14892:6;14881:9;14877:22;14856:53;:::i;:::-;14846:63;;14802:117;14958:2;14984:53;15029:7;15020:6;15009:9;15005:22;14984:53;:::i;:::-;14974:63;;14929:118;15086:2;15112:53;15157:7;15148:6;15137:9;15133:22;15112:53;:::i;:::-;15102:63;;15057:118;15242:2;15231:9;15227:18;15214:32;15273:18;15265:6;15262:30;15259:117;;;15295:79;;:::i;:::-;15259:117;15400:62;15454:7;15445:6;15434:9;15430:22;15400:62;:::i;:::-;15390:72;;15185:287;14536:943;;;;;;;:::o;15485:104::-;15530:7;15559:24;15577:5;15559:24;:::i;:::-;15548:35;;15485:104;;;:::o;15595:142::-;15698:32;15724:5;15698:32;:::i;:::-;15693:3;15686:45;15595:142;;:::o;15743:254::-;15852:4;15890:2;15879:9;15875:18;15867:26;;15903:87;15987:1;15976:9;15972:17;15963:6;15903:87;:::i;:::-;15743:254;;;;:::o;16003:474::-;16071:6;16079;16128:2;16116:9;16107:7;16103:23;16099:32;16096:119;;;16134:79;;:::i;:::-;16096:119;16254:1;16279:53;16324:7;16315:6;16304:9;16300:22;16279:53;:::i;:::-;16269:63;;16225:117;16381:2;16407:53;16452:7;16443:6;16432:9;16428:22;16407:53;:::i;:::-;16397:63;;16352:118;16003:474;;;;;:::o;16483:164::-;16623:16;16619:1;16611:6;16607:14;16600:40;16483:164;:::o;16653:366::-;16795:3;16816:67;16880:2;16875:3;16816:67;:::i;:::-;16809:74;;16892:93;16981:3;16892:93;:::i;:::-;17010:2;17005:3;17001:12;16994:19;;16653:366;;;:::o;17025:419::-;17191:4;17229:2;17218:9;17214:18;17206:26;;17278:9;17272:4;17268:20;17264:1;17253:9;17249:17;17242:47;17306:131;17432:4;17306:131;:::i;:::-;17298:139;;17025:419;;;:::o;17450:180::-;17498:77;17495:1;17488:88;17595:4;17592:1;17585:15;17619:4;17616:1;17609:15;17636:320;17680:6;17717:1;17711:4;17707:12;17697:22;;17764:1;17758:4;17754:12;17785:18;17775:81;;17841:4;17833:6;17829:17;17819:27;;17775:81;17903:2;17895:6;17892:14;17872:18;17869:38;17866:84;;17922:18;;:::i;:::-;17866:84;17687:269;17636:320;;;:::o;17962:168::-;18102:20;18098:1;18090:6;18086:14;18079:44;17962:168;:::o;18136:366::-;18278:3;18299:67;18363:2;18358:3;18299:67;:::i;:::-;18292:74;;18375:93;18464:3;18375:93;:::i;:::-;18493:2;18488:3;18484:12;18477:19;;18136:366;;;:::o;18508:419::-;18674:4;18712:2;18701:9;18697:18;18689:26;;18761:9;18755:4;18751:20;18747:1;18736:9;18732:17;18725:47;18789:131;18915:4;18789:131;:::i;:::-;18781:139;;18508:419;;;:::o;18933:169::-;19073:21;19069:1;19061:6;19057:14;19050:45;18933:169;:::o;19108:366::-;19250:3;19271:67;19335:2;19330:3;19271:67;:::i;:::-;19264:74;;19347:93;19436:3;19347:93;:::i;:::-;19465:2;19460:3;19456:12;19449:19;;19108:366;;;:::o;19480:419::-;19646:4;19684:2;19673:9;19669:18;19661:26;;19733:9;19727:4;19723:20;19719:1;19708:9;19704:17;19697:47;19761:131;19887:4;19761:131;:::i;:::-;19753:139;;19480:419;;;:::o;19905:180::-;19953:77;19950:1;19943:88;20050:4;20047:1;20040:15;20074:4;20071:1;20064:15;20091:191;20131:3;20150:20;20168:1;20150:20;:::i;:::-;20145:25;;20184:20;20202:1;20184:20;:::i;:::-;20179:25;;20227:1;20224;20220:9;20213:16;;20248:3;20245:1;20242:10;20239:36;;;20255:18;;:::i;:::-;20239:36;20091:191;;;;:::o;20288:168::-;20428:20;20424:1;20416:6;20412:14;20405:44;20288:168;:::o;20462:366::-;20604:3;20625:67;20689:2;20684:3;20625:67;:::i;:::-;20618:74;;20701:93;20790:3;20701:93;:::i;:::-;20819:2;20814:3;20810:12;20803:19;;20462:366;;;:::o;20834:419::-;21000:4;21038:2;21027:9;21023:18;21015:26;;21087:9;21081:4;21077:20;21073:1;21062:9;21058:17;21051:47;21115:131;21241:4;21115:131;:::i;:::-;21107:139;;20834:419;;;:::o;21259:442::-;21408:4;21446:2;21435:9;21431:18;21423:26;;21459:71;21527:1;21516:9;21512:17;21503:6;21459:71;:::i;:::-;21540:72;21608:2;21597:9;21593:18;21584:6;21540:72;:::i;:::-;21622;21690:2;21679:9;21675:18;21666:6;21622:72;:::i;:::-;21259:442;;;;;;:::o;21707:137::-;21761:5;21792:6;21786:13;21777:22;;21808:30;21832:5;21808:30;:::i;:::-;21707:137;;;;:::o;21850:345::-;21917:6;21966:2;21954:9;21945:7;21941:23;21937:32;21934:119;;;21972:79;;:::i;:::-;21934:119;22092:1;22117:61;22170:7;22161:6;22150:9;22146:22;22117:61;:::i;:::-;22107:71;;22063:125;21850:345;;;;:::o;22201:164::-;22341:16;22337:1;22329:6;22325:14;22318:40;22201:164;:::o;22371:366::-;22513:3;22534:67;22598:2;22593:3;22534:67;:::i;:::-;22527:74;;22610:93;22699:3;22610:93;:::i;:::-;22728:2;22723:3;22719:12;22712:19;;22371:366;;;:::o;22743:419::-;22909:4;22947:2;22936:9;22932:18;22924:26;;22996:9;22990:4;22986:20;22982:1;22971:9;22967:17;22960:47;23024:131;23150:4;23024:131;:::i;:::-;23016:139;;22743:419;;;:::o;23168:233::-;23207:3;23230:24;23248:5;23230:24;:::i;:::-;23221:33;;23276:66;23269:5;23266:77;23263:103;;23346:18;;:::i;:::-;23263:103;23393:1;23386:5;23382:13;23375:20;;23168:233;;;:::o;23407:165::-;23547:17;23543:1;23535:6;23531:14;23524:41;23407:165;:::o;23578:366::-;23720:3;23741:67;23805:2;23800:3;23741:67;:::i;:::-;23734:74;;23817:93;23906:3;23817:93;:::i;:::-;23935:2;23930:3;23926:12;23919:19;;23578:366;;;:::o;23950:419::-;24116:4;24154:2;24143:9;24139:18;24131:26;;24203:9;24197:4;24193:20;24189:1;24178:9;24174:17;24167:47;24231:131;24357:4;24231:131;:::i;:::-;24223:139;;23950:419;;;:::o;24375:98::-;24426:6;24460:5;24454:12;24444:22;;24375:98;;;:::o;24479:168::-;24562:11;24596:6;24591:3;24584:19;24636:4;24631:3;24627:14;24612:29;;24479:168;;;;:::o;24653:373::-;24739:3;24767:38;24799:5;24767:38;:::i;:::-;24821:70;24884:6;24879:3;24821:70;:::i;:::-;24814:77;;24900:65;24958:6;24953:3;24946:4;24939:5;24935:16;24900:65;:::i;:::-;24990:29;25012:6;24990:29;:::i;:::-;24985:3;24981:39;24974:46;;24743:283;24653:373;;;;:::o;25032:419::-;25171:4;25209:2;25198:9;25194:18;25186:26;;25222:71;25290:1;25279:9;25275:17;25266:6;25222:71;:::i;:::-;25340:9;25334:4;25330:20;25325:2;25314:9;25310:18;25303:48;25368:76;25439:4;25430:6;25368:76;:::i;:::-;25360:84;;25032:419;;;;;:::o;25457:442::-;25606:4;25644:2;25633:9;25629:18;25621:26;;25657:71;25725:1;25714:9;25710:17;25701:6;25657:71;:::i;:::-;25738:72;25806:2;25795:9;25791:18;25782:6;25738:72;:::i;:::-;25820;25888:2;25877:9;25873:18;25864:6;25820:72;:::i;:::-;25457:442;;;;;;:::o;25905:332::-;26026:4;26064:2;26053:9;26049:18;26041:26;;26077:71;26145:1;26134:9;26130:17;26121:6;26077:71;:::i;:::-;26158:72;26226:2;26215:9;26211:18;26202:6;26158:72;:::i;:::-;25905:332;;;;;:::o;26243:163::-;26383:15;26379:1;26371:6;26367:14;26360:39;26243:163;:::o;26412:366::-;26554:3;26575:67;26639:2;26634:3;26575:67;:::i;:::-;26568:74;;26651:93;26740:3;26651:93;:::i;:::-;26769:2;26764:3;26760:12;26753:19;;26412:366;;;:::o;26784:419::-;26950:4;26988:2;26977:9;26973:18;26965:26;;27037:9;27031:4;27027:20;27023:1;27012:9;27008:17;27001:47;27065:131;27191:4;27065:131;:::i;:::-;27057:139;;26784:419;;;:::o;27209:143::-;27266:5;27297:6;27291:13;27282:22;;27313:33;27340:5;27313:33;:::i;:::-;27209:143;;;;:::o;27358:351::-;27428:6;27477:2;27465:9;27456:7;27452:23;27448:32;27445:119;;;27483:79;;:::i;:::-;27445:119;27603:1;27628:64;27684:7;27675:6;27664:9;27660:22;27628:64;:::i;:::-;27618:74;;27574:128;27358:351;;;;:::o;27715:134::-;27773:9;27806:37;27837:5;27806:37;:::i;:::-;27793:50;;27715:134;;;:::o;27855:147::-;27950:45;27989:5;27950:45;:::i;:::-;27945:3;27938:58;27855:147;;:::o;28008:348::-;28137:4;28175:2;28164:9;28160:18;28152:26;;28188:79;28264:1;28253:9;28249:17;28240:6;28188:79;:::i;:::-;28277:72;28345:2;28334:9;28330:18;28321:6;28277:72;:::i;:::-;28008:348;;;;;:::o;28362:180::-;28410:77;28407:1;28400:88;28507:4;28504:1;28497:15;28531:4;28528:1;28521:15;28548:170;28688:22;28684:1;28676:6;28672:14;28665:46;28548:170;:::o;28724:366::-;28866:3;28887:67;28951:2;28946:3;28887:67;:::i;:::-;28880:74;;28963:93;29052:3;28963:93;:::i;:::-;29081:2;29076:3;29072:12;29065:19;;28724:366;;;:::o;29096:419::-;29262:4;29300:2;29289:9;29285:18;29277:26;;29349:9;29343:4;29339:20;29335:1;29324:9;29320:17;29313:47;29377:131;29503:4;29377:131;:::i;:::-;29369:139;;29096:419;;;:::o;29521:148::-;29623:11;29660:3;29645:18;;29521:148;;;;:::o;29675:232::-;29815:34;29811:1;29803:6;29799:14;29792:58;29888:7;29883:2;29875:6;29871:15;29864:32;29675:232;:::o;29917:418::-;30077:3;30102:85;30184:2;30179:3;30102:85;:::i;:::-;30095:92;;30200:93;30289:3;30200:93;:::i;:::-;30322:2;30317:3;30313:12;30306:19;;29917:418;;;:::o;30345:410::-;30451:3;30483:39;30516:5;30483:39;:::i;:::-;30542:89;30624:6;30619:3;30542:89;:::i;:::-;30535:96;;30644:65;30702:6;30697:3;30690:4;30683:5;30679:16;30644:65;:::i;:::-;30738:6;30733:3;30729:16;30722:23;;30455:300;30345:410;;;;:::o;30765:557::-;30998:3;31024:148;31168:3;31024:148;:::i;:::-;31017:155;;31193:95;31284:3;31275:6;31193:95;:::i;:::-;31186:102;;31309:3;31302:10;;30765:557;;;;:::o;31332:332::-;31394:4;31492:18;31484:6;31481:30;31478:56;;;31514:18;;:::i;:::-;31478:56;31556:29;31578:6;31556:29;:::i;:::-;31548:37;;31648:4;31642;31638:15;31630:23;;31332:332;;;:::o;31674:458::-;31763:5;31792:66;31808:49;31850:6;31808:49;:::i;:::-;31792:66;:::i;:::-;31783:75;;31885:6;31878:5;31871:21;31927:4;31920:5;31916:16;31969:3;31960:6;31955:3;31951:16;31948:25;31945:112;;;31976:79;;:::i;:::-;31945:112;32070:52;32115:6;32110:3;32105;32070:52;:::i;:::-;31769:363;31674:458;;;;;:::o;32160:371::-;32227:5;32280:3;32273:4;32265:6;32261:17;32257:27;32247:122;;32288:79;;:::i;:::-;32247:122;32402:6;32396:13;32431:90;32517:3;32509:6;32502:4;32494:6;32490:17;32431:90;:::i;:::-;32422:99;;32233:298;32160:371;;;;:::o;32541:552::-;32621:6;32674:2;32662:9;32653:7;32649:23;32645:32;32642:119;;;32680:79;;:::i;:::-;32642:119;32829:1;32818:9;32814:17;32808:24;32863:18;32855:6;32852:30;32849:117;;;32885:79;;:::i;:::-;32849:117;32994:74;33060:7;33051:6;33040:9;33036:22;32994:74;:::i;:::-;32984:84;;32775:307;32541:552;;;;:::o;33103:222::-;33247:66;33243:1;33235:6;33231:14;33224:90;33103:222;:::o;33335:418::-;33495:3;33520:85;33602:2;33597:3;33520:85;:::i;:::-;33513:92;;33618:93;33707:3;33618:93;:::i;:::-;33740:2;33735:3;33731:12;33724:19;;33335:418;;;:::o;33763:400::-;33907:66;33903:1;33895:6;33891:14;33884:90;34012:34;34007:2;33999:6;33995:15;33988:59;34085:66;34080:2;34072:6;34068:15;34061:91;33763:400;:::o;34173:418::-;34333:3;34358:85;34440:2;34435:3;34358:85;:::i;:::-;34351:92;;34456:93;34545:3;34456:93;:::i;:::-;34578:2;34573:3;34569:12;34562:19;;34173:418;;;:::o;34601:222::-;34745:66;34741:1;34733:6;34729:14;34722:90;34601:222;:::o;34833:416::-;34993:3;35018:84;35100:1;35095:3;35018:84;:::i;:::-;35011:91;;35115:93;35204:3;35115:93;:::i;:::-;35237:1;35232:3;35228:11;35221:18;;34833:416;;;:::o;35259:222::-;35403:66;35399:1;35391:6;35387:14;35380:90;35259:222;:::o;35491:418::-;35651:3;35676:85;35758:2;35753:3;35676:85;:::i;:::-;35669:92;;35774:93;35863:3;35774:93;:::i;:::-;35896:2;35891:3;35887:12;35880:19;;35491:418;;;:::o;35919:222::-;36063:66;36059:1;36051:6;36047:14;36040:90;35919:222;:::o;36151:418::-;36311:3;36336:85;36418:2;36413:3;36336:85;:::i;:::-;36329:92;;36434:93;36523:3;36434:93;:::i;:::-;36556:2;36551:3;36547:12;36540:19;;36151:418;;;:::o;36579:151::-;36719:3;36715:1;36707:6;36703:14;36696:27;36579:151;:::o;36736:400::-;36896:3;36917:84;36999:1;36994:3;36917:84;:::i;:::-;36910:91;;37010:93;37099:3;37010:93;:::i;:::-;37128:1;37123:3;37119:11;37112:18;;36736:400;;;:::o;37142:2351::-;38024:3;38046:148;38190:3;38046:148;:::i;:::-;38039:155;;38211:95;38302:3;38293:6;38211:95;:::i;:::-;38204:102;;38323:148;38467:3;38323:148;:::i;:::-;38316:155;;38488:148;38632:3;38488:148;:::i;:::-;38481:155;;38653:95;38744:3;38735:6;38653:95;:::i;:::-;38646:102;;38765:148;38909:3;38765:148;:::i;:::-;38758:155;;38930:95;39021:3;39012:6;38930:95;:::i;:::-;38923:102;;39042:148;39186:3;39042:148;:::i;:::-;39035:155;;39207:95;39298:3;39289:6;39207:95;:::i;:::-;39200:102;;39319:148;39463:3;39319:148;:::i;:::-;39312:155;;39484:3;39477:10;;37142:2351;;;;;;;:::o;39499:179::-;39639:31;39635:1;39627:6;39623:14;39616:55;39499:179;:::o;39684:402::-;39844:3;39865:85;39947:2;39942:3;39865:85;:::i;:::-;39858:92;;39959:93;40048:3;39959:93;:::i;:::-;40077:2;40072:3;40068:12;40061:19;;39684:402;;;:::o;40092:541::-;40325:3;40347:148;40491:3;40347:148;:::i;:::-;40340:155;;40512:95;40603:3;40594:6;40512:95;:::i;:::-;40505:102;;40624:3;40617:10;;40092:541;;;;:::o;40639:160::-;40779:12;40775:1;40767:6;40763:14;40756:36;40639:160;:::o;40805:366::-;40947:3;40968:67;41032:2;41027:3;40968:67;:::i;:::-;40961:74;;41044:93;41133:3;41044:93;:::i;:::-;41162:2;41157:3;41153:12;41146:19;;40805:366;;;:::o;41177:419::-;41343:4;41381:2;41370:9;41366:18;41358:26;;41430:9;41424:4;41420:20;41416:1;41405:9;41401:17;41394:47;41458:131;41584:4;41458:131;:::i;:::-;41450:139;;41177:419;;;:::o;41602:194::-;41642:4;41662:20;41680:1;41662:20;:::i;:::-;41657:25;;41696:20;41714:1;41696:20;:::i;:::-;41691:25;;41740:1;41737;41733:9;41725:17;;41764:1;41758:4;41755:11;41752:37;;;41769:18;;:::i;:::-;41752:37;41602:194;;;;:::o;41802:171::-;41841:3;41864:24;41882:5;41864:24;:::i;:::-;41855:33;;41910:4;41903:5;41900:15;41897:41;;41918:18;;:::i;:::-;41897:41;41965:1;41958:5;41954:13;41947:20;;41802:171;;;:::o;41979:640::-;42174:4;42212:3;42201:9;42197:19;42189:27;;42226:71;42294:1;42283:9;42279:17;42270:6;42226:71;:::i;:::-;42307:72;42375:2;42364:9;42360:18;42351:6;42307:72;:::i;:::-;42389;42457:2;42446:9;42442:18;42433:6;42389:72;:::i;:::-;42508:9;42502:4;42498:20;42493:2;42482:9;42478:18;42471:48;42536:76;42607:4;42598:6;42536:76;:::i;:::-;42528:84;;41979:640;;;;;;;:::o;42625:141::-;42681:5;42712:6;42706:13;42697:22;;42728:32;42754:5;42728:32;:::i;:::-;42625:141;;;;:::o;42772:349::-;42841:6;42890:2;42878:9;42869:7;42865:23;42861:32;42858:119;;;42896:79;;:::i;:::-;42858:119;43016:1;43041:63;43096:7;43087:6;43076:9;43072:22;43041:63;:::i;:::-;43031:73;;42987:127;42772:349;;;;:::o;43127:180::-;43175:77;43172:1;43165:88;43272:4;43269:1;43262:15;43296:4;43293:1;43286:15;43313:185;43353:1;43370:20;43388:1;43370:20;:::i;:::-;43365:25;;43404:20;43422:1;43404:20;:::i;:::-;43399:25;;43443:1;43433:35;;43448:18;;:::i;:::-;43433:35;43490:1;43487;43483:9;43478:14;;43313:185;;;;:::o;43504:176::-;43536:1;43553:20;43571:1;43553:20;:::i;:::-;43548:25;;43587:20;43605:1;43587:20;:::i;:::-;43582:25;;43626:1;43616:35;;43631:18;;:::i;:::-;43616:35;43672:1;43669;43665:9;43660:14;;43504:176;;;;:::o;43686:410::-;43726:7;43749:20;43767:1;43749:20;:::i;:::-;43744:25;;43783:20;43801:1;43783:20;:::i;:::-;43778:25;;43838:1;43835;43831:9;43860:30;43878:11;43860:30;:::i;:::-;43849:41;;44039:1;44030:7;44026:15;44023:1;44020:22;44000:1;43993:9;43973:83;43950:139;;44069:18;;:::i;:::-;43950:139;43734:362;43686:410;;;;:::o;44102:180::-;44150:77;44147:1;44140:88;44247:4;44244:1;44237:15;44271:4;44268:1;44261:15
Swarm Source
ipfs://fd85b315a71bafd2ff8a13d5164a8c7845d126c1a3062671ef896ad55d97ac4c
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.