Overview
APE Balance
APE Value
$0.00More Info
Private Name Tags
ContractCreator
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-10 */ /** * _ _ _ _ _ _ _ _ * /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ / /\ * / \ \ / \ \ / \ \ \ \ \ / \ \ / \ \ \_\ \ / / \ * / /\ \ \ / /\ \ \ / /\ \ \ /\ \_\ / /\ \ \ / /\ \ \ /\__ \ / / /\ \ * / / /\ \_\ / / /\ \_\ / / /\ \ \ / /\/_// / /\ \_\ / / /\ \ \ / /_ \ \ /_/ /\ \ \ * / / /_/ / // / /_/ / / / / / \ \_\ _ / / / / /_/_ \/_/ / / / \ \_\ / / /\ \ \ \ \ \_\ \ \ * / / /__\/ // / /__\/ / / / / / / //\ \ / / / / /____/\ / / / \/_/ / / / \/_/ \ \/__\ \ \ * / / /_____// / /_____/ / / / / / / \ \_\ / / / / /\____\/ / / / / / / \_____\ \ \ * / / / / / /\ \ \ / / /___/ / / / / /_/ / / / / /______ / / /________ / / / \ \ \ * / / / / / / \ \ \/ / /____\/ / / / /__\/ / / / /_______\/ / /_________\/_/ / \ \ \ * \/_/ \/_/ \_\/\/_________/ \/_______/ \/__________/\/____________/\_\/ \_\/ * * 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 pragma solidity ^0.8.0; /** * _ _ _ _ _ _ _ _ * /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ / /\ * / \ \ / \ \ / \ \ \ \ \ / \ \ / \ \ \_\ \ / / \ * / /\ \ \ / /\ \ \ / /\ \ \ /\ \_\ / /\ \ \ / /\ \ \ /\__ \ / / /\ \ * / / /\ \_\ / / /\ \_\ / / /\ \ \ / /\/_// / /\ \_\ / / /\ \ \ / /_ \ \ /_/ /\ \ \ * / / /_/ / // / /_/ / / / / / \ \_\ _ / / / / /_/_ \/_/ / / / \ \_\ / / /\ \ \ \ \ \_\ \ \ * / / /__\/ // / /__\/ / / / / / / //\ \ / / / / /____/\ / / / \/_/ / / / \/_/ \ \/__\ \ \ * / / /_____// / /_____/ / / / / / / \ \_\ / / / / /\____\/ / / / / / / \_____\ \ \ * / / / / / /\ \ \ / / /___/ / / / / /_/ / / / / /______ / / /________ / / / \ \ \ * / / / / / / \ \ \/ / /____\/ / / / /__\/ / / / /_______\/ / /_________\/_/ / \ \ \ * \/_/ \/_/ \_\/\/_________/ \/_______/ \/__________/\/____________/\_\/ \_\/ * * On-chain Project 9 datas, by SoftWave. **/ contract ProjectNineData { address payable internal deployer; address payable public nftContract; bool private contractLocked = false; string internal constant SVG_HEADER = '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 24 24"><rect width="100%" height="100%" fill="#E73879"/>'; string internal constant SVG_FOOTER = "</svg>"; bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; 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; // Row-major RGBA data (3x3 pixels, 3364 bytes) Trait[] traits; // Array of traits for the token } mapping(uint256 => NineData) private nineData; // Stores data for each NFT 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); } /** * Setting NFTContract address */ 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"); // Update the coordination state variable updateCoord = Coordination(startX, startY, width, height); } /** * Locking contract */ 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 == 24 * 24 * 3, "Invalid pixel data length" ); nineData[tokenId].pixelData = pixelData; } } function storeTraits(uint256 tokenId, Trait[] memory traits) external onlyDeployer unlocked { uint256 len = traits.length; require(len > 0, "Traits cannot be empty"); // Resize existing traits array delete nineData[tokenId].traits; // Clear previous data for (uint256 i = 0; i < len; 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; // Clear existing traits for (uint256 j = 0; j < traits.length; j++) { nineData[tokenId].traits.push(traits[j]); } } } // Retrieve traits for a token 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; } /** * @notice Retrieve RGB pixel data for a NFT. * @param tokenId The ID of the NFT. * @return The RGB pixel data. */ 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; } /** * @notice Generate the SVG for a NFT from its pixel data. * @param tokenId The ID of the NFT. */ function getNineSVG(uint256 tokenId) external view returns (string memory svg) { require(tokenId < MAX_LIMIT, "Invalid tokenId"); bytes memory pixels = nineData[tokenId].pixelData; require(pixels.length > 0, "Pixel data not set"); bytes memory result = abi.encodePacked(SVG_HEADER); // Start with the header bytes memory buffer = new bytes(7); // Buffer for color hex for (uint256 y = 0; y < 24; y++) { for (uint256 x = 0; x < 24; x++) { uint256 p = (y * 24 + x) * 3; if ( pixels[p] == 0xe7 && pixels[p + 1] == 0x38 && pixels[p + 2] == 0x79 ) { continue; // Skip background pixels #E73879 } // Convert RGB to hex buffer[0] = "#"; for (uint256 i = 0; i < 3; i++) { uint8 value = uint8(pixels[p + i]); buffer[1 + i * 2] = _HEX_SYMBOLS[value >> 4]; buffer[2 + i * 2] = _HEX_SYMBOLS[value & 0xf]; } // Append rect to the result result = abi.encodePacked( result, '<rect x="', toString(x), '" y="', toString(y), '" width="1" height="1" shape-rendering="crispEdges" fill="', string(buffer), '"/>' ); } } svg = string(abi.encodePacked(result, SVG_FOOTER)); // Append footer } function updatePixelData(uint256 tokenId, bytes memory colors) external onlyNFTContract { // Ensure the color array length matches the defined coordination area uint256 area = updateCoord.width * updateCoord.height; require(colors.length == area * 3, "Colors array length mismatch"); // Retrieve pixel data bytes memory pixelData = nineData[tokenId].pixelData; // Ensure pixel data exists require(pixelData.length == PIXEL_DATA_SIZE, "Invalid pixel data"); // Update pixels in the specified rectangle 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; // Calculate the pixel index in the byte array uint256 pixelIndex = (y * 24 + x) * 3; // Calculate the color index in the input `colors` array uint256 colorIndex = (row * updateCoord.width + col) * 3; // Update the RGB values for the pixel pixelData[pixelIndex] = colors[colorIndex]; pixelData[pixelIndex + 1] = colors[colorIndex + 1]; pixelData[pixelIndex + 2] = colors[colorIndex + 2]; } } // Save updated pixel data nineData[tokenId].pixelData = pixelData; } /// @dev Returns the base 10 decimal representation of `value`. function toString(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. str := add(mload(0x40), 0x80) // Update the free memory pointer to allocate. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str let w := not(0) for { let temp := value } 1 { } { str := add(str, w) // `sub(str, 1)`. // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } } // 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; mapping(address => bool) private WLAccounts; mapping(address => uint256) public mintCounts; uint256 private immutable seed; IERC20 public paymentToken; uint256 public mintPrice; 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 setMintPrice(uint256 _mintPrice) external onlyDeployer { mintPrice = _mintPrice; } 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 += 1; } 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"); string memory svgImage = dataContract.getNineSVG(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":"data:image/svg+xml;base64,', Base64.encode(bytes(svgImage)), '", "attributes":', traits, '}' ) ) ) ) ); } function updatePixelData(uint256 tokenId, bytes memory newPixelData) external { require(ownerOf(tokenId) == msg.sender, "Not token owner"); dataContract.updatePixelData(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
[{"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":"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":"uint256","name":"_mintPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"setPaymentToken","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
60c06040526108ae608090815250348015610018575f80fd5b506040516149ef3803806149ef833981810160405281019061003a9190610373565b806040518060400160405280600b81526020017f50726f6a6563744e696e650000000000000000000000000000000000000000008152506040518060400160405280600581526020017f504e494e45000000000000000000000000000000000000000000000000000000815250815f90816100b591906105eb565b5080600190816100c591906105eb565b5050505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610138575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161012f91906106c9565b60405180910390fd5b6101478161021760201b60201c565b5081600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600d5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550608051600c819055506001436101de919061070f565b40306040516020016101f19291906107b0565b604051602081830303815290604052805190602001205f1c60a0818152505050506107db565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610307826102de565b9050919050565b610317816102fd565b8114610321575f80fd5b50565b5f815190506103328161030e565b92915050565b5f610342826102de565b9050919050565b61035281610338565b811461035c575f80fd5b50565b5f8151905061036d81610349565b92915050565b5f8060408385031215610389576103886102da565b5b5f61039685828601610324565b92505060206103a78582860161035f565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061042c57607f821691505b60208210810361043f5761043e6103e8565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026104a17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610466565b6104ab8683610466565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6104ef6104ea6104e5846104c3565b6104cc565b6104c3565b9050919050565b5f819050919050565b610508836104d5565b61051c610514826104f6565b848454610472565b825550505050565b5f90565b610530610524565b61053b8184846104ff565b505050565b5b8181101561055e576105535f82610528565b600181019050610541565b5050565b601f8211156105a35761057481610445565b61057d84610457565b8101602085101561058c578190505b6105a061059885610457565b830182610540565b50505b505050565b5f82821c905092915050565b5f6105c35f19846008026105a8565b1980831691505092915050565b5f6105db83836105b4565b9150826002028217905092915050565b6105f4826103b1565b67ffffffffffffffff81111561060d5761060c6103bb565b5b6106178254610415565b610622828285610562565b5f60209050601f831160018114610653575f8415610641578287015190505b61064b85826105d0565b8655506106b2565b601f19841661066186610445565b5f5b8281101561068857848901518255600182019150602085019450602081019050610663565b868310156106a557848901516106a1601f8916826105b4565b8355505b6001600288020188555050505b505050505050565b6106c3816102fd565b82525050565b5f6020820190506106dc5f8301846106ba565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610719826104c3565b9150610724836104c3565b925082820390508181111561073c5761073b6106e2565b5b92915050565b5f819050919050565b5f819050919050565b61076561076082610742565b61074b565b82525050565b5f8160601b9050919050565b5f6107818261076b565b9050919050565b5f61079282610777565b9050919050565b6107aa6107a5826102fd565b610788565b82525050565b5f6107bb8285610754565b6020820191506107cb8284610799565b6014820191508190509392505050565b60805160a0516141de6108115f395f61240701525f818161082c01528181610d9c015281816114460152611a1c01526141de5ff3fe608060405234801561000f575f80fd5b5060043610610204575f3560e01c806355234ec0116101185780638da5cb5b116100ab578063c87b56dd1161007a578063c87b56dd146105c4578063d5f39488146105f4578063e985e9c514610612578063f2fde38b14610642578063f4a0a5281461065e57610204565b80638da5cb5b1461055057806395d89b411461056e578063a22cb4651461058c578063b88d4fde146105a857610204565b80636a326ab1116100e75780636a326ab1146104dc57806370a08231146104f8578063715018a6146105285780638099b0021461053257610204565b806355234ec0146104545780636352211e1461047257806367b06aee146104a25780636817c76c146104be57610204565b80632061cea71161019b57806332cb6b0c1161016a57806332cb6b0c1461039e57806342842e0e146103bc57806349df728c146103d85780634f6ccce7146103f4578063532778791461042457610204565b80632061cea71461031857806323b872dd146103345780632f745c59146103505780633013ce291461038057610204565b806309fd8212116101d757806309fd8212146102a25780630d668818146102d25780631249c58b146102f057806318160ddd146102fa57610204565b806301ffc9a71461020857806306fdde0314610238578063081812fc14610256578063095ea7b314610286575b5f80fd5b610222600480360381019061021d9190612d54565b61067a565b60405161022f9190612d99565b60405180910390f35b6102406106f3565b60405161024d9190612e22565b60405180910390f35b610270600480360381019061026b9190612e75565b610782565b60405161027d9190612edf565b60405180910390f35b6102a0600480360381019061029b9190612f22565b61079d565b005b6102bc60048036038101906102b79190612f60565b6107b3565b6040516102c99190612d99565b60405180910390f35b6102da610805565b6040516102e79190612fe6565b60405180910390f35b6102f861082a565b005b610302610ac3565b60405161030f919061300e565b60405180910390f35b610332600480360381019061032d9190613153565b610acf565b005b61034e600480360381019061034991906131ad565b610bd2565b005b61036a60048036038101906103659190612f22565b610cd1565b604051610377919061300e565b60405180910390f35b610388610d75565b604051610395919061321d565b60405180910390f35b6103a6610d9a565b6040516103b3919061300e565b60405180910390f35b6103d660048036038101906103d191906131ad565b610dbe565b005b6103f260048036038101906103ed9190613271565b610ddd565b005b61040e60048036038101906104099190612e75565b610ff1565b60405161041b919061300e565b60405180910390f35b61043e60048036038101906104399190612f60565b611063565b60405161044b919061300e565b60405180910390f35b61045c611078565b604051610469919061300e565b60405180910390f35b61048c60048036038101906104879190612e75565b61107e565b6040516104999190612edf565b60405180910390f35b6104bc60048036038101906104b79190613360565b61108f565b005b6104c66111a9565b6040516104d3919061300e565b60405180910390f35b6104f660048036038101906104f19190612f60565b6111af565b005b610512600480360381019061050d9190612f60565b611281565b60405161051f919061300e565b60405180910390f35b610530611337565b005b61053a61134a565b604051610547919061300e565b60405180910390f35b61055861134f565b6040516105659190612edf565b60405180910390f35b610576611377565b6040516105839190612e22565b60405180910390f35b6105a660048036038101906105a191906133d1565b611407565b005b6105c260048036038101906105bd919061340f565b61141d565b005b6105de60048036038101906105d99190612e75565b611442565b6040516105eb9190612e22565b60405180910390f35b6105fc611648565b60405161060991906134af565b60405180910390f35b61062c600480360381019061062791906134c8565b61166d565b6040516106399190612d99565b60405180910390f35b61065c60048036038101906106579190612f60565b6116fb565b005b61067860048036038101906106739190612e75565b61177f565b005b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806106ec57506106eb82611818565b5b9050919050565b60605f805461070190613533565b80601f016020809104026020016040519081016040528092919081815260200182805461072d90613533565b80156107785780601f1061074f57610100808354040283529160200191610778565b820191905f5260205f20905b81548152906001019060200180831161075b57829003601f168201915b5050505050905090565b5f61078c826118f9565b506107968261197f565b9050919050565b6107af82826107aa6119b8565b6119bf565b5050565b5f600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f0000000000000000000000000000000000000000000000000000000000000000610853610ac3565b10610893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088a906135ad565b60405180910390fd5b5f601154116108d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108ce90613615565b60405180910390fd5b5f600390506108e5336107b3565b156108fa576001816108f79190613660565b90505b80600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410610979576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610970906136dd565b60405180910390fd5b60105f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33306011546040518463ffffffff1660e01b81526004016109d9939291906136fb565b6020604051808303815f875af11580156109f5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a199190613744565b610a58576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a4f906137b9565b60405180910390fd5b5f610a616119d1565b9050610a6d3382611a72565b600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610aba906137d7565b91905055505050565b5f600880549050905090565b3373ffffffffffffffffffffffffffffffffffffffff16610aef8361107e565b73ffffffffffffffffffffffffffffffffffffffff1614610b45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3c90613868565b60405180910390fd5b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632061cea783836040518363ffffffff1660e01b8152600401610ba19291906138d8565b5f604051808303815f87803b158015610bb8575f80fd5b505af1158015610bca573d5f803e3d5ffd5b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610c42575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401610c399190612edf565b60405180910390fd5b5f610c558383610c506119b8565b611a8f565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610ccb578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610cc293929190613906565b60405180910390fd5b50505050565b5f610cdb83611281565b8210610d205782826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610d1792919061393b565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b60105f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b610dd883838360405180602001604052805f81525061141d565b505050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e63906139ac565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610eda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed190613a14565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f519190612edf565b602060405180830381865afa158015610f6c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f909190613a46565b6040518363ffffffff1660e01b8152600401610fad929190613a91565b6020604051808303815f875af1158015610fc9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fed9190613744565b5050565b5f610ffa610ac3565b821061103f575f826040517fa57d13dc00000000000000000000000000000000000000000000000000000000815260040161103692919061393b565b60405180910390fd5b6008828154811061105357611052613ab8565b5b905f5260205f2001549050919050565b600f602052805f5260405f205f915090505481565b600c5481565b5f611088826118f9565b9050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461111e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611115906139ac565b60405180910390fd5b5f5b81518110156111a5576001600e5f84848151811061114157611140613ab8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508080600101915050611120565b5050565b60115481565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461123e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611235906139ac565b60405180910390fd5b8060105f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036112f2575f6040517f89c62b640000000000000000000000000000000000000000000000000000000081526004016112e99190612edf565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61133f611ba9565b6113485f611c30565b565b600381565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606001805461138690613533565b80601f01602080910402602001604051908101604052809291908181526020018280546113b290613533565b80156113fd5780601f106113d4576101008083540402835291602001916113fd565b820191905f5260205f20905b8154815290600101906020018083116113e057829003601f168201915b5050505050905090565b6114196114126119b8565b8383611cf3565b5050565b611428848484610bd2565b61143c6114336119b8565b85858585611e5c565b50505050565b60607f000000000000000000000000000000000000000000000000000000000000000082106114a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149d90613b2f565b60405180910390fd5b5f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c969272c846040518263ffffffff1660e01b8152600401611501919061300e565b5f60405180830381865afa15801561151b573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906115439190613beb565b90505f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e1dc0761856040518263ffffffff1660e01b81526004016115a0919061300e565b5f60405180830381865afa1580156115ba573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906115e29190613beb565b90506116206115f085612008565b6115f984612161565b8360405160200161160c93929190613e50565b604051602081830303815290604052612161565b6040516020016116309190613f01565b60405160208183030381529060405292505050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b611703611ba9565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611773575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161176a9190612edf565b60405180910390fd5b61177c81611c30565b50565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461180e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611805906139ac565b60405180910390fd5b8060118190555050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806118e257507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806118f257506118f18261218e565b5b9050919050565b5f80611904836121f7565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361197657826040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161196d919061300e565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6119cc8383836001612230565b505050565b5f80600c5411611a16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0d90613f6c565b60405180910390fd5b5f600c547f0000000000000000000000000000000000000000000000000000000000000000611a459190613f8a565b90505f611a51826123ef565b9050600c5f815480929190611a6590613fbd565b9190505550809250505090565b611a8b828260405180602001604052805f81525061245c565b5050565b5f80611a9c85858561247f565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611adf57611ada8461268a565b611b1e565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b1d57611b1c81856126ce565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611b5f57611b5a846127a5565b611b9e565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b9d57611b9c8585612865565b5b5b809150509392505050565b611bb16119b8565b73ffffffffffffffffffffffffffffffffffffffff16611bcf61134f565b73ffffffffffffffffffffffffffffffffffffffff1614611c2e57611bf26119b8565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611c259190612edf565b60405180910390fd5b565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d6357816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611d5a9190612edf565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611e4f9190612d99565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115612001578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b8152600401611eba9493929190613fe4565b6020604051808303815f875af1925050508015611ef557506040513d601f19601f82011682018060405250810190611ef29190614042565b60015b611f76573d805f8114611f23576040519150601f19603f3d011682016040523d82523d5f602084013e611f28565b606091505b505f815103611f6e57836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611f659190612edf565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611fff57836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611ff69190612edf565b60405180910390fd5b505b5050505050565b60605f820361204e576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061215c565b5f8290505f5b5f821461207d578080612066906137d7565b915050600a82612076919061409a565b9150612054565b5f8167ffffffffffffffff8111156120985761209761302f565b5b6040519080825280601f01601f1916602001820160405280156120ca5781602001600182028036833780820191505090505b5090505b5f8514612155576001826120e29190613f8a565b9150600a856120f191906140ca565b60306120fd9190613660565b60f81b81838151811061211357612112613ab8565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a8561214e919061409a565b94506120ce565b8093505050505b919050565b6060612187826040518060600160405280604081526020016141696040913960016128e9565b9050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061226857505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b1561239a575f612277846118f9565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156122e157508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156122f457506122f2818461166d565b155b1561233657826040517fa9fbf51f00000000000000000000000000000000000000000000000000000000815260040161232d9190612edf565b60405180910390fd5b811561239857838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b5f806108ad90505f600180836124059190613f8a565b7f000000000000000000000000000000000000000000000000000000000000000061243091906140ca565b61243a9190613660565b905081848261244991906140fa565b61245391906140ca565b92505050919050565b6124668383612a78565b61247a6124716119b8565b5f858585611e5c565b505050565b5f8061248a846121f7565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146124cb576124ca818486612b6b565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146125565761250a5f855f80612230565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146125d557600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f6126d883611281565b90505f60075f8481526020019081526020015f205490505f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050828214612777575f815f8581526020019081526020015f2054905080825f8581526020019081526020015f20819055508260075f8381526020019081526020015f2081905550505b60075f8581526020019081526020015f205f9055805f8481526020019081526020015f205f90555050505050565b5f60016008805490506127b89190613f8a565b90505f60095f8481526020019081526020015f205490505f600883815481106127e4576127e3613ab8565b5b905f5260205f2001549050806008838154811061280457612803613ab8565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f9055600880548061284c5761284b61413b565b5b600190038181905f5260205f20015f9055905550505050565b5f600161287184611281565b61287b9190613f8a565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b60605f8451036129095760405180602001604052805f8152509050612a71565b5f8261293a57600360028651600461292191906140fa565b61292b9190613660565b612935919061409a565b612961565b60036002865161294a9190613660565b612954919061409a565b600461296091906140fa565b5b90505f8167ffffffffffffffff81111561297e5761297d61302f565b5b6040519080825280601f01601f1916602001820160405280156129b05781602001600182028036833780820191505090505b509050600185016020820187885189016020810180515f82525b82841015612a25576003840193508351603f8160121c168701518653600186019550603f81600c1c168701518653600186019550603f8160061c168701518653600186019550603f81168701518653600186019550506129ca565b8082528915612a655760038c510660018114612a485760028114612a5b57612a63565b603d6001870353603d6002870353612a63565b603d60018703535b505b50505050505080925050505b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612ae8575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612adf9190612edf565b60405180910390fd5b5f612af483835f611a8f565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612b66575f6040517f73c6ac6e000000000000000000000000000000000000000000000000000000008152600401612b5d9190612edf565b60405180910390fd5b505050565b612b76838383612c2e565b612c29575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612bea57806040517f7e273289000000000000000000000000000000000000000000000000000000008152600401612be1919061300e565b60405180910390fd5b81816040517f177e802f000000000000000000000000000000000000000000000000000000008152600401612c2092919061393b565b60405180910390fd5b505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612ce557508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612ca65750612ca5848461166d565b5b80612ce457508273ffffffffffffffffffffffffffffffffffffffff16612ccc8361197f565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612d3381612cff565b8114612d3d575f80fd5b50565b5f81359050612d4e81612d2a565b92915050565b5f60208284031215612d6957612d68612cf7565b5b5f612d7684828501612d40565b91505092915050565b5f8115159050919050565b612d9381612d7f565b82525050565b5f602082019050612dac5f830184612d8a565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612df482612db2565b612dfe8185612dbc565b9350612e0e818560208601612dcc565b612e1781612dda565b840191505092915050565b5f6020820190508181035f830152612e3a8184612dea565b905092915050565b5f819050919050565b612e5481612e42565b8114612e5e575f80fd5b50565b5f81359050612e6f81612e4b565b92915050565b5f60208284031215612e8a57612e89612cf7565b5b5f612e9784828501612e61565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612ec982612ea0565b9050919050565b612ed981612ebf565b82525050565b5f602082019050612ef25f830184612ed0565b92915050565b612f0181612ebf565b8114612f0b575f80fd5b50565b5f81359050612f1c81612ef8565b92915050565b5f8060408385031215612f3857612f37612cf7565b5b5f612f4585828601612f0e565b9250506020612f5685828601612e61565b9150509250929050565b5f60208284031215612f7557612f74612cf7565b5b5f612f8284828501612f0e565b91505092915050565b5f819050919050565b5f612fae612fa9612fa484612ea0565b612f8b565b612ea0565b9050919050565b5f612fbf82612f94565b9050919050565b5f612fd082612fb5565b9050919050565b612fe081612fc6565b82525050565b5f602082019050612ff95f830184612fd7565b92915050565b61300881612e42565b82525050565b5f6020820190506130215f830184612fff565b92915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61306582612dda565b810181811067ffffffffffffffff821117156130845761308361302f565b5b80604052505050565b5f613096612cee565b90506130a2828261305c565b919050565b5f67ffffffffffffffff8211156130c1576130c061302f565b5b6130ca82612dda565b9050602081019050919050565b828183375f83830152505050565b5f6130f76130f2846130a7565b61308d565b9050828152602081018484840111156131135761311261302b565b5b61311e8482856130d7565b509392505050565b5f82601f83011261313a57613139613027565b5b813561314a8482602086016130e5565b91505092915050565b5f806040838503121561316957613168612cf7565b5b5f61317685828601612e61565b925050602083013567ffffffffffffffff81111561319757613196612cfb565b5b6131a385828601613126565b9150509250929050565b5f805f606084860312156131c4576131c3612cf7565b5b5f6131d186828701612f0e565b93505060206131e286828701612f0e565b92505060406131f386828701612e61565b9150509250925092565b5f61320782612fb5565b9050919050565b613217816131fd565b82525050565b5f6020820190506132305f83018461320e565b92915050565b5f61324082612ebf565b9050919050565b61325081613236565b811461325a575f80fd5b50565b5f8135905061326b81613247565b92915050565b5f6020828403121561328657613285612cf7565b5b5f6132938482850161325d565b91505092915050565b5f67ffffffffffffffff8211156132b6576132b561302f565b5b602082029050602081019050919050565b5f80fd5b5f6132dd6132d88461329c565b61308d565b90508083825260208201905060208402830185811115613300576132ff6132c7565b5b835b8181101561332957806133158882612f0e565b845260208401935050602081019050613302565b5050509392505050565b5f82601f83011261334757613346613027565b5b81356133578482602086016132cb565b91505092915050565b5f6020828403121561337557613374612cf7565b5b5f82013567ffffffffffffffff81111561339257613391612cfb565b5b61339e84828501613333565b91505092915050565b6133b081612d7f565b81146133ba575f80fd5b50565b5f813590506133cb816133a7565b92915050565b5f80604083850312156133e7576133e6612cf7565b5b5f6133f485828601612f0e565b9250506020613405858286016133bd565b9150509250929050565b5f805f806080858703121561342757613426612cf7565b5b5f61343487828801612f0e565b945050602061344587828801612f0e565b935050604061345687828801612e61565b925050606085013567ffffffffffffffff81111561347757613476612cfb565b5b61348387828801613126565b91505092959194509250565b5f61349982612ea0565b9050919050565b6134a98161348f565b82525050565b5f6020820190506134c25f8301846134a0565b92915050565b5f80604083850312156134de576134dd612cf7565b5b5f6134eb85828601612f0e565b92505060206134fc85828601612f0e565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061354a57607f821691505b60208210810361355d5761355c613506565b5b50919050565b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f613597601283612dbc565b91506135a282613563565b602082019050919050565b5f6020820190508181035f8301526135c48161358b565b9050919050565b7f4d696e74696e67206e6f7420656e61626c6564000000000000000000000000005f82015250565b5f6135ff601383612dbc565b915061360a826135cb565b602082019050919050565b5f6020820190508181035f83015261362c816135f3565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61366a82612e42565b915061367583612e42565b925082820190508082111561368d5761368c613633565b5b92915050565b7f45786365656473206d696e74206c696d697400000000000000000000000000005f82015250565b5f6136c7601283612dbc565b91506136d282613693565b602082019050919050565b5f6020820190508181035f8301526136f4816136bb565b9050919050565b5f60608201905061370e5f830186612ed0565b61371b6020830185612ed0565b6137286040830184612fff565b949350505050565b5f8151905061373e816133a7565b92915050565b5f6020828403121561375957613758612cf7565b5b5f61376684828501613730565b91505092915050565b7f5061796d656e74206661696c65640000000000000000000000000000000000005f82015250565b5f6137a3600e83612dbc565b91506137ae8261376f565b602082019050919050565b5f6020820190508181035f8301526137d081613797565b9050919050565b5f6137e182612e42565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361381357613812613633565b5b600182019050919050565b7f4e6f7420746f6b656e206f776e657200000000000000000000000000000000005f82015250565b5f613852600f83612dbc565b915061385d8261381e565b602082019050919050565b5f6020820190508181035f83015261387f81613846565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f6138aa82613886565b6138b48185613890565b93506138c4818560208601612dcc565b6138cd81612dda565b840191505092915050565b5f6040820190506138eb5f830185612fff565b81810360208301526138fd81846138a0565b90509392505050565b5f6060820190506139195f830186612ed0565b6139266020830185612fff565b6139336040830184612ed0565b949350505050565b5f60408201905061394e5f830185612ed0565b61395b6020830184612fff565b9392505050565b7f4f6e6c79204465706c6f7965722e0000000000000000000000000000000000005f82015250565b5f613996600e83612dbc565b91506139a182613962565b602082019050919050565b5f6020820190508181035f8301526139c38161398a565b9050919050565b7f496e76616c696420746f6b656e000000000000000000000000000000000000005f82015250565b5f6139fe600d83612dbc565b9150613a09826139ca565b602082019050919050565b5f6020820190508181035f830152613a2b816139f2565b9050919050565b5f81519050613a4081612e4b565b92915050565b5f60208284031215613a5b57613a5a612cf7565b5b5f613a6884828501613a32565b91505092915050565b5f613a7b82612fb5565b9050919050565b613a8b81613a71565b82525050565b5f604082019050613aa45f830185613a82565b613ab16020830184612fff565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f546f6b656e20646f6573206e6f742065786973740000000000000000000000005f82015250565b5f613b19601483612dbc565b9150613b2482613ae5565b602082019050919050565b5f6020820190508181035f830152613b4681613b0d565b9050919050565b5f67ffffffffffffffff821115613b6757613b6661302f565b5b613b7082612dda565b9050602081019050919050565b5f613b8f613b8a84613b4d565b61308d565b905082815260208101848484011115613bab57613baa61302b565b5b613bb6848285612dcc565b509392505050565b5f82601f830112613bd257613bd1613027565b5b8151613be2848260208601613b7d565b91505092915050565b5f60208284031215613c0057613bff612cf7565b5b5f82015167ffffffffffffffff811115613c1d57613c1c612cfb565b5b613c2984828501613bbe565b91505092915050565b5f81905092915050565b7f7b226e616d65223a2250726f6a656374204e696e6520230000000000000000005f82015250565b5f613c70601783613c32565b9150613c7b82613c3c565b601782019050919050565b5f613c9082612db2565b613c9a8185613c32565b9350613caa818560208601612dcc565b80840191505092915050565b7f222c20226465736372697074696f6e223a2250726f6a6563742039202d2073615f8201527f76696e6720656e64616e67657265642063726561747572657320696e20756e6360208201527f686172746564207265616c6d732e222c00000000000000000000000000000000604082015250565b5f613d36605083613c32565b9150613d4182613cb6565b605082019050919050565b7f22696d616765223a22646174613a696d6167652f7376672b786d6c3b626173655f8201527f36342c0000000000000000000000000000000000000000000000000000000000602082015250565b5f613da6602383613c32565b9150613db182613d4c565b602382019050919050565b7f222c202261747472696275746573223a000000000000000000000000000000005f82015250565b5f613df0601083613c32565b9150613dfb82613dbc565b601082019050919050565b7f7d000000000000000000000000000000000000000000000000000000000000005f82015250565b5f613e3a600183613c32565b9150613e4582613e06565b600182019050919050565b5f613e5a82613c64565b9150613e668286613c86565b9150613e7182613d2a565b9150613e7c82613d9a565b9150613e888285613c86565b9150613e9382613de4565b9150613e9f8284613c86565b9150613eaa82613e2e565b9150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f613eeb601d83613c32565b9150613ef682613eb7565b601d82019050919050565b5f613f0b82613edf565b9150613f178284613c86565b915081905092915050565b7f416c6c206d696e746564000000000000000000000000000000000000000000005f82015250565b5f613f56600a83612dbc565b9150613f6182613f22565b602082019050919050565b5f6020820190508181035f830152613f8381613f4a565b9050919050565b5f613f9482612e42565b9150613f9f83612e42565b9250828203905081811115613fb757613fb6613633565b5b92915050565b5f613fc782612e42565b91505f8203613fd957613fd8613633565b5b600182039050919050565b5f608082019050613ff75f830187612ed0565b6140046020830186612ed0565b6140116040830185612fff565b818103606083015261402381846138a0565b905095945050505050565b5f8151905061403c81612d2a565b92915050565b5f6020828403121561405757614056612cf7565b5b5f6140648482850161402e565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6140a482612e42565b91506140af83612e42565b9250826140bf576140be61406d565b5b828204905092915050565b5f6140d482612e42565b91506140df83612e42565b9250826140ef576140ee61406d565b5b828206905092915050565b5f61410482612e42565b915061410f83612e42565b925082820261411d81612e42565b9150828204841483151761413457614133613633565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220b80c746532ce4709106d1b25805f4f2252f41c70c34710f940ddb06948d07ecd64736f6c634300081a00330000000000000000000000007593c518d9d56cc74c9afa953ff7b8c050e265eb000000000000000000000000b931e339b4f5eb3d4d039ce1451426754063c711
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610204575f3560e01c806355234ec0116101185780638da5cb5b116100ab578063c87b56dd1161007a578063c87b56dd146105c4578063d5f39488146105f4578063e985e9c514610612578063f2fde38b14610642578063f4a0a5281461065e57610204565b80638da5cb5b1461055057806395d89b411461056e578063a22cb4651461058c578063b88d4fde146105a857610204565b80636a326ab1116100e75780636a326ab1146104dc57806370a08231146104f8578063715018a6146105285780638099b0021461053257610204565b806355234ec0146104545780636352211e1461047257806367b06aee146104a25780636817c76c146104be57610204565b80632061cea71161019b57806332cb6b0c1161016a57806332cb6b0c1461039e57806342842e0e146103bc57806349df728c146103d85780634f6ccce7146103f4578063532778791461042457610204565b80632061cea71461031857806323b872dd146103345780632f745c59146103505780633013ce291461038057610204565b806309fd8212116101d757806309fd8212146102a25780630d668818146102d25780631249c58b146102f057806318160ddd146102fa57610204565b806301ffc9a71461020857806306fdde0314610238578063081812fc14610256578063095ea7b314610286575b5f80fd5b610222600480360381019061021d9190612d54565b61067a565b60405161022f9190612d99565b60405180910390f35b6102406106f3565b60405161024d9190612e22565b60405180910390f35b610270600480360381019061026b9190612e75565b610782565b60405161027d9190612edf565b60405180910390f35b6102a0600480360381019061029b9190612f22565b61079d565b005b6102bc60048036038101906102b79190612f60565b6107b3565b6040516102c99190612d99565b60405180910390f35b6102da610805565b6040516102e79190612fe6565b60405180910390f35b6102f861082a565b005b610302610ac3565b60405161030f919061300e565b60405180910390f35b610332600480360381019061032d9190613153565b610acf565b005b61034e600480360381019061034991906131ad565b610bd2565b005b61036a60048036038101906103659190612f22565b610cd1565b604051610377919061300e565b60405180910390f35b610388610d75565b604051610395919061321d565b60405180910390f35b6103a6610d9a565b6040516103b3919061300e565b60405180910390f35b6103d660048036038101906103d191906131ad565b610dbe565b005b6103f260048036038101906103ed9190613271565b610ddd565b005b61040e60048036038101906104099190612e75565b610ff1565b60405161041b919061300e565b60405180910390f35b61043e60048036038101906104399190612f60565b611063565b60405161044b919061300e565b60405180910390f35b61045c611078565b604051610469919061300e565b60405180910390f35b61048c60048036038101906104879190612e75565b61107e565b6040516104999190612edf565b60405180910390f35b6104bc60048036038101906104b79190613360565b61108f565b005b6104c66111a9565b6040516104d3919061300e565b60405180910390f35b6104f660048036038101906104f19190612f60565b6111af565b005b610512600480360381019061050d9190612f60565b611281565b60405161051f919061300e565b60405180910390f35b610530611337565b005b61053a61134a565b604051610547919061300e565b60405180910390f35b61055861134f565b6040516105659190612edf565b60405180910390f35b610576611377565b6040516105839190612e22565b60405180910390f35b6105a660048036038101906105a191906133d1565b611407565b005b6105c260048036038101906105bd919061340f565b61141d565b005b6105de60048036038101906105d99190612e75565b611442565b6040516105eb9190612e22565b60405180910390f35b6105fc611648565b60405161060991906134af565b60405180910390f35b61062c600480360381019061062791906134c8565b61166d565b6040516106399190612d99565b60405180910390f35b61065c60048036038101906106579190612f60565b6116fb565b005b61067860048036038101906106739190612e75565b61177f565b005b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806106ec57506106eb82611818565b5b9050919050565b60605f805461070190613533565b80601f016020809104026020016040519081016040528092919081815260200182805461072d90613533565b80156107785780601f1061074f57610100808354040283529160200191610778565b820191905f5260205f20905b81548152906001019060200180831161075b57829003601f168201915b5050505050905090565b5f61078c826118f9565b506107968261197f565b9050919050565b6107af82826107aa6119b8565b6119bf565b5050565b5f600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000008ae610853610ac3565b10610893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088a906135ad565b60405180910390fd5b5f601154116108d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108ce90613615565b60405180910390fd5b5f600390506108e5336107b3565b156108fa576001816108f79190613660565b90505b80600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410610979576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610970906136dd565b60405180910390fd5b60105f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33306011546040518463ffffffff1660e01b81526004016109d9939291906136fb565b6020604051808303815f875af11580156109f5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a199190613744565b610a58576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a4f906137b9565b60405180910390fd5b5f610a616119d1565b9050610a6d3382611a72565b600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610aba906137d7565b91905055505050565b5f600880549050905090565b3373ffffffffffffffffffffffffffffffffffffffff16610aef8361107e565b73ffffffffffffffffffffffffffffffffffffffff1614610b45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3c90613868565b60405180910390fd5b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632061cea783836040518363ffffffff1660e01b8152600401610ba19291906138d8565b5f604051808303815f87803b158015610bb8575f80fd5b505af1158015610bca573d5f803e3d5ffd5b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610c42575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401610c399190612edf565b60405180910390fd5b5f610c558383610c506119b8565b611a8f565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610ccb578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610cc293929190613906565b60405180910390fd5b50505050565b5f610cdb83611281565b8210610d205782826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610d1792919061393b565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b60105f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000008ae81565b610dd883838360405180602001604052805f81525061141d565b505050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e63906139ac565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610eda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed190613a14565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f519190612edf565b602060405180830381865afa158015610f6c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f909190613a46565b6040518363ffffffff1660e01b8152600401610fad929190613a91565b6020604051808303815f875af1158015610fc9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fed9190613744565b5050565b5f610ffa610ac3565b821061103f575f826040517fa57d13dc00000000000000000000000000000000000000000000000000000000815260040161103692919061393b565b60405180910390fd5b6008828154811061105357611052613ab8565b5b905f5260205f2001549050919050565b600f602052805f5260405f205f915090505481565b600c5481565b5f611088826118f9565b9050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461111e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611115906139ac565b60405180910390fd5b5f5b81518110156111a5576001600e5f84848151811061114157611140613ab8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508080600101915050611120565b5050565b60115481565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461123e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611235906139ac565b60405180910390fd5b8060105f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036112f2575f6040517f89c62b640000000000000000000000000000000000000000000000000000000081526004016112e99190612edf565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61133f611ba9565b6113485f611c30565b565b600381565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606001805461138690613533565b80601f01602080910402602001604051908101604052809291908181526020018280546113b290613533565b80156113fd5780601f106113d4576101008083540402835291602001916113fd565b820191905f5260205f20905b8154815290600101906020018083116113e057829003601f168201915b5050505050905090565b6114196114126119b8565b8383611cf3565b5050565b611428848484610bd2565b61143c6114336119b8565b85858585611e5c565b50505050565b60607f00000000000000000000000000000000000000000000000000000000000008ae82106114a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149d90613b2f565b60405180910390fd5b5f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c969272c846040518263ffffffff1660e01b8152600401611501919061300e565b5f60405180830381865afa15801561151b573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906115439190613beb565b90505f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e1dc0761856040518263ffffffff1660e01b81526004016115a0919061300e565b5f60405180830381865afa1580156115ba573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906115e29190613beb565b90506116206115f085612008565b6115f984612161565b8360405160200161160c93929190613e50565b604051602081830303815290604052612161565b6040516020016116309190613f01565b60405160208183030381529060405292505050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b611703611ba9565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611773575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161176a9190612edf565b60405180910390fd5b61177c81611c30565b50565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461180e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611805906139ac565b60405180910390fd5b8060118190555050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806118e257507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806118f257506118f18261218e565b5b9050919050565b5f80611904836121f7565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361197657826040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161196d919061300e565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6119cc8383836001612230565b505050565b5f80600c5411611a16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0d90613f6c565b60405180910390fd5b5f600c547f00000000000000000000000000000000000000000000000000000000000008ae611a459190613f8a565b90505f611a51826123ef565b9050600c5f815480929190611a6590613fbd565b9190505550809250505090565b611a8b828260405180602001604052805f81525061245c565b5050565b5f80611a9c85858561247f565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611adf57611ada8461268a565b611b1e565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b1d57611b1c81856126ce565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611b5f57611b5a846127a5565b611b9e565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b9d57611b9c8585612865565b5b5b809150509392505050565b611bb16119b8565b73ffffffffffffffffffffffffffffffffffffffff16611bcf61134f565b73ffffffffffffffffffffffffffffffffffffffff1614611c2e57611bf26119b8565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611c259190612edf565b60405180910390fd5b565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d6357816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611d5a9190612edf565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611e4f9190612d99565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115612001578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b8152600401611eba9493929190613fe4565b6020604051808303815f875af1925050508015611ef557506040513d601f19601f82011682018060405250810190611ef29190614042565b60015b611f76573d805f8114611f23576040519150601f19603f3d011682016040523d82523d5f602084013e611f28565b606091505b505f815103611f6e57836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611f659190612edf565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611fff57836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611ff69190612edf565b60405180910390fd5b505b5050505050565b60605f820361204e576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061215c565b5f8290505f5b5f821461207d578080612066906137d7565b915050600a82612076919061409a565b9150612054565b5f8167ffffffffffffffff8111156120985761209761302f565b5b6040519080825280601f01601f1916602001820160405280156120ca5781602001600182028036833780820191505090505b5090505b5f8514612155576001826120e29190613f8a565b9150600a856120f191906140ca565b60306120fd9190613660565b60f81b81838151811061211357612112613ab8565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a8561214e919061409a565b94506120ce565b8093505050505b919050565b6060612187826040518060600160405280604081526020016141696040913960016128e9565b9050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061226857505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b1561239a575f612277846118f9565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156122e157508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156122f457506122f2818461166d565b155b1561233657826040517fa9fbf51f00000000000000000000000000000000000000000000000000000000815260040161232d9190612edf565b60405180910390fd5b811561239857838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b5f806108ad90505f600180836124059190613f8a565b7f1d93f8781546d49749f5792f91519f8b133016907bd2e157110bd1853402973561243091906140ca565b61243a9190613660565b905081848261244991906140fa565b61245391906140ca565b92505050919050565b6124668383612a78565b61247a6124716119b8565b5f858585611e5c565b505050565b5f8061248a846121f7565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146124cb576124ca818486612b6b565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146125565761250a5f855f80612230565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146125d557600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f6126d883611281565b90505f60075f8481526020019081526020015f205490505f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050828214612777575f815f8581526020019081526020015f2054905080825f8581526020019081526020015f20819055508260075f8381526020019081526020015f2081905550505b60075f8581526020019081526020015f205f9055805f8481526020019081526020015f205f90555050505050565b5f60016008805490506127b89190613f8a565b90505f60095f8481526020019081526020015f205490505f600883815481106127e4576127e3613ab8565b5b905f5260205f2001549050806008838154811061280457612803613ab8565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f9055600880548061284c5761284b61413b565b5b600190038181905f5260205f20015f9055905550505050565b5f600161287184611281565b61287b9190613f8a565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b60605f8451036129095760405180602001604052805f8152509050612a71565b5f8261293a57600360028651600461292191906140fa565b61292b9190613660565b612935919061409a565b612961565b60036002865161294a9190613660565b612954919061409a565b600461296091906140fa565b5b90505f8167ffffffffffffffff81111561297e5761297d61302f565b5b6040519080825280601f01601f1916602001820160405280156129b05781602001600182028036833780820191505090505b509050600185016020820187885189016020810180515f82525b82841015612a25576003840193508351603f8160121c168701518653600186019550603f81600c1c168701518653600186019550603f8160061c168701518653600186019550603f81168701518653600186019550506129ca565b8082528915612a655760038c510660018114612a485760028114612a5b57612a63565b603d6001870353603d6002870353612a63565b603d60018703535b505b50505050505080925050505b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612ae8575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612adf9190612edf565b60405180910390fd5b5f612af483835f611a8f565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612b66575f6040517f73c6ac6e000000000000000000000000000000000000000000000000000000008152600401612b5d9190612edf565b60405180910390fd5b505050565b612b76838383612c2e565b612c29575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612bea57806040517f7e273289000000000000000000000000000000000000000000000000000000008152600401612be1919061300e565b60405180910390fd5b81816040517f177e802f000000000000000000000000000000000000000000000000000000008152600401612c2092919061393b565b60405180910390fd5b505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612ce557508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612ca65750612ca5848461166d565b5b80612ce457508273ffffffffffffffffffffffffffffffffffffffff16612ccc8361197f565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612d3381612cff565b8114612d3d575f80fd5b50565b5f81359050612d4e81612d2a565b92915050565b5f60208284031215612d6957612d68612cf7565b5b5f612d7684828501612d40565b91505092915050565b5f8115159050919050565b612d9381612d7f565b82525050565b5f602082019050612dac5f830184612d8a565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612df482612db2565b612dfe8185612dbc565b9350612e0e818560208601612dcc565b612e1781612dda565b840191505092915050565b5f6020820190508181035f830152612e3a8184612dea565b905092915050565b5f819050919050565b612e5481612e42565b8114612e5e575f80fd5b50565b5f81359050612e6f81612e4b565b92915050565b5f60208284031215612e8a57612e89612cf7565b5b5f612e9784828501612e61565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612ec982612ea0565b9050919050565b612ed981612ebf565b82525050565b5f602082019050612ef25f830184612ed0565b92915050565b612f0181612ebf565b8114612f0b575f80fd5b50565b5f81359050612f1c81612ef8565b92915050565b5f8060408385031215612f3857612f37612cf7565b5b5f612f4585828601612f0e565b9250506020612f5685828601612e61565b9150509250929050565b5f60208284031215612f7557612f74612cf7565b5b5f612f8284828501612f0e565b91505092915050565b5f819050919050565b5f612fae612fa9612fa484612ea0565b612f8b565b612ea0565b9050919050565b5f612fbf82612f94565b9050919050565b5f612fd082612fb5565b9050919050565b612fe081612fc6565b82525050565b5f602082019050612ff95f830184612fd7565b92915050565b61300881612e42565b82525050565b5f6020820190506130215f830184612fff565b92915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61306582612dda565b810181811067ffffffffffffffff821117156130845761308361302f565b5b80604052505050565b5f613096612cee565b90506130a2828261305c565b919050565b5f67ffffffffffffffff8211156130c1576130c061302f565b5b6130ca82612dda565b9050602081019050919050565b828183375f83830152505050565b5f6130f76130f2846130a7565b61308d565b9050828152602081018484840111156131135761311261302b565b5b61311e8482856130d7565b509392505050565b5f82601f83011261313a57613139613027565b5b813561314a8482602086016130e5565b91505092915050565b5f806040838503121561316957613168612cf7565b5b5f61317685828601612e61565b925050602083013567ffffffffffffffff81111561319757613196612cfb565b5b6131a385828601613126565b9150509250929050565b5f805f606084860312156131c4576131c3612cf7565b5b5f6131d186828701612f0e565b93505060206131e286828701612f0e565b92505060406131f386828701612e61565b9150509250925092565b5f61320782612fb5565b9050919050565b613217816131fd565b82525050565b5f6020820190506132305f83018461320e565b92915050565b5f61324082612ebf565b9050919050565b61325081613236565b811461325a575f80fd5b50565b5f8135905061326b81613247565b92915050565b5f6020828403121561328657613285612cf7565b5b5f6132938482850161325d565b91505092915050565b5f67ffffffffffffffff8211156132b6576132b561302f565b5b602082029050602081019050919050565b5f80fd5b5f6132dd6132d88461329c565b61308d565b90508083825260208201905060208402830185811115613300576132ff6132c7565b5b835b8181101561332957806133158882612f0e565b845260208401935050602081019050613302565b5050509392505050565b5f82601f83011261334757613346613027565b5b81356133578482602086016132cb565b91505092915050565b5f6020828403121561337557613374612cf7565b5b5f82013567ffffffffffffffff81111561339257613391612cfb565b5b61339e84828501613333565b91505092915050565b6133b081612d7f565b81146133ba575f80fd5b50565b5f813590506133cb816133a7565b92915050565b5f80604083850312156133e7576133e6612cf7565b5b5f6133f485828601612f0e565b9250506020613405858286016133bd565b9150509250929050565b5f805f806080858703121561342757613426612cf7565b5b5f61343487828801612f0e565b945050602061344587828801612f0e565b935050604061345687828801612e61565b925050606085013567ffffffffffffffff81111561347757613476612cfb565b5b61348387828801613126565b91505092959194509250565b5f61349982612ea0565b9050919050565b6134a98161348f565b82525050565b5f6020820190506134c25f8301846134a0565b92915050565b5f80604083850312156134de576134dd612cf7565b5b5f6134eb85828601612f0e565b92505060206134fc85828601612f0e565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061354a57607f821691505b60208210810361355d5761355c613506565b5b50919050565b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f613597601283612dbc565b91506135a282613563565b602082019050919050565b5f6020820190508181035f8301526135c48161358b565b9050919050565b7f4d696e74696e67206e6f7420656e61626c6564000000000000000000000000005f82015250565b5f6135ff601383612dbc565b915061360a826135cb565b602082019050919050565b5f6020820190508181035f83015261362c816135f3565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61366a82612e42565b915061367583612e42565b925082820190508082111561368d5761368c613633565b5b92915050565b7f45786365656473206d696e74206c696d697400000000000000000000000000005f82015250565b5f6136c7601283612dbc565b91506136d282613693565b602082019050919050565b5f6020820190508181035f8301526136f4816136bb565b9050919050565b5f60608201905061370e5f830186612ed0565b61371b6020830185612ed0565b6137286040830184612fff565b949350505050565b5f8151905061373e816133a7565b92915050565b5f6020828403121561375957613758612cf7565b5b5f61376684828501613730565b91505092915050565b7f5061796d656e74206661696c65640000000000000000000000000000000000005f82015250565b5f6137a3600e83612dbc565b91506137ae8261376f565b602082019050919050565b5f6020820190508181035f8301526137d081613797565b9050919050565b5f6137e182612e42565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361381357613812613633565b5b600182019050919050565b7f4e6f7420746f6b656e206f776e657200000000000000000000000000000000005f82015250565b5f613852600f83612dbc565b915061385d8261381e565b602082019050919050565b5f6020820190508181035f83015261387f81613846565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f6138aa82613886565b6138b48185613890565b93506138c4818560208601612dcc565b6138cd81612dda565b840191505092915050565b5f6040820190506138eb5f830185612fff565b81810360208301526138fd81846138a0565b90509392505050565b5f6060820190506139195f830186612ed0565b6139266020830185612fff565b6139336040830184612ed0565b949350505050565b5f60408201905061394e5f830185612ed0565b61395b6020830184612fff565b9392505050565b7f4f6e6c79204465706c6f7965722e0000000000000000000000000000000000005f82015250565b5f613996600e83612dbc565b91506139a182613962565b602082019050919050565b5f6020820190508181035f8301526139c38161398a565b9050919050565b7f496e76616c696420746f6b656e000000000000000000000000000000000000005f82015250565b5f6139fe600d83612dbc565b9150613a09826139ca565b602082019050919050565b5f6020820190508181035f830152613a2b816139f2565b9050919050565b5f81519050613a4081612e4b565b92915050565b5f60208284031215613a5b57613a5a612cf7565b5b5f613a6884828501613a32565b91505092915050565b5f613a7b82612fb5565b9050919050565b613a8b81613a71565b82525050565b5f604082019050613aa45f830185613a82565b613ab16020830184612fff565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f546f6b656e20646f6573206e6f742065786973740000000000000000000000005f82015250565b5f613b19601483612dbc565b9150613b2482613ae5565b602082019050919050565b5f6020820190508181035f830152613b4681613b0d565b9050919050565b5f67ffffffffffffffff821115613b6757613b6661302f565b5b613b7082612dda565b9050602081019050919050565b5f613b8f613b8a84613b4d565b61308d565b905082815260208101848484011115613bab57613baa61302b565b5b613bb6848285612dcc565b509392505050565b5f82601f830112613bd257613bd1613027565b5b8151613be2848260208601613b7d565b91505092915050565b5f60208284031215613c0057613bff612cf7565b5b5f82015167ffffffffffffffff811115613c1d57613c1c612cfb565b5b613c2984828501613bbe565b91505092915050565b5f81905092915050565b7f7b226e616d65223a2250726f6a656374204e696e6520230000000000000000005f82015250565b5f613c70601783613c32565b9150613c7b82613c3c565b601782019050919050565b5f613c9082612db2565b613c9a8185613c32565b9350613caa818560208601612dcc565b80840191505092915050565b7f222c20226465736372697074696f6e223a2250726f6a6563742039202d2073615f8201527f76696e6720656e64616e67657265642063726561747572657320696e20756e6360208201527f686172746564207265616c6d732e222c00000000000000000000000000000000604082015250565b5f613d36605083613c32565b9150613d4182613cb6565b605082019050919050565b7f22696d616765223a22646174613a696d6167652f7376672b786d6c3b626173655f8201527f36342c0000000000000000000000000000000000000000000000000000000000602082015250565b5f613da6602383613c32565b9150613db182613d4c565b602382019050919050565b7f222c202261747472696275746573223a000000000000000000000000000000005f82015250565b5f613df0601083613c32565b9150613dfb82613dbc565b601082019050919050565b7f7d000000000000000000000000000000000000000000000000000000000000005f82015250565b5f613e3a600183613c32565b9150613e4582613e06565b600182019050919050565b5f613e5a82613c64565b9150613e668286613c86565b9150613e7182613d2a565b9150613e7c82613d9a565b9150613e888285613c86565b9150613e9382613de4565b9150613e9f8284613c86565b9150613eaa82613e2e565b9150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f613eeb601d83613c32565b9150613ef682613eb7565b601d82019050919050565b5f613f0b82613edf565b9150613f178284613c86565b915081905092915050565b7f416c6c206d696e746564000000000000000000000000000000000000000000005f82015250565b5f613f56600a83612dbc565b9150613f6182613f22565b602082019050919050565b5f6020820190508181035f830152613f8381613f4a565b9050919050565b5f613f9482612e42565b9150613f9f83612e42565b9250828203905081811115613fb757613fb6613633565b5b92915050565b5f613fc782612e42565b91505f8203613fd957613fd8613633565b5b600182039050919050565b5f608082019050613ff75f830187612ed0565b6140046020830186612ed0565b6140116040830185612fff565b818103606083015261402381846138a0565b905095945050505050565b5f8151905061403c81612d2a565b92915050565b5f6020828403121561405757614056612cf7565b5b5f6140648482850161402e565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6140a482612e42565b91506140af83612e42565b9250826140bf576140be61406d565b5b828204905092915050565b5f6140d482612e42565b91506140df83612e42565b9250826140ef576140ee61406d565b5b828206905092915050565b5f61410482612e42565b915061410f83612e42565b925082820261411d81612e42565b9150828204841483151761413457614133613633565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220b80c746532ce4709106d1b25805f4f2252f41c70c34710f940ddb06948d07ecd64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007593c518d9d56cc74c9afa953ff7b8c050e265eb000000000000000000000000b931e339b4f5eb3d4d039ce1451426754063c711
-----Decoded View---------------
Arg [0] : dataContractAddress (address): 0x7593c518d9d56cC74c9Afa953ff7B8c050E265eB
Arg [1] : _deployer (address): 0xb931E339b4f5eB3D4D039CE1451426754063C711
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000007593c518d9d56cc74c9afa953ff7b8c050e265eb
Arg [1] : 000000000000000000000000b931e339b4f5eb3d4d039ce1451426754063c711
Deployed Bytecode Sourcemap
155357:4674:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;125682:224;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108762:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109934:158;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109753:115;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;156799:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;155417:35;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156927:710;;;:::i;:::-;;126326:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;158861:217;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;110603:588;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125990:260;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;155782:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;155459:42;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;111262:134;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;159828:200;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;126507:231;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;155687:45;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;155562:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108575:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156586:205;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;155815:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156339:123;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;108300:213;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;134112:103;;;:::i;:::-;;155508:47;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;133437:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108922:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110164:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111467:236;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;157903:950;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;155593:31;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110381:155;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;134370:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;156473:105;;;;;;;;;;;;;:::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;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;156799:120::-;156864:4;156888:10;:23;156899:11;156888:23;;;;;;;;;;;;;;;;;;;;;;;;;156881:30;;156799:120;;;:::o;155417:35::-;;;;;;;;;;;;;:::o;156927:710::-;156987:10;156971:13;:11;:13::i;:::-;:26;156963:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;157051:1;157039:9;;:13;157031:45;;;;;;;;;;;;:::i;:::-;;;;;;;;;157127:18;155554:1;157127:40;;157182:25;157196:10;157182:13;:25::i;:::-;157178:73;;;157238:1;157224:15;;;;;:::i;:::-;;;157178:73;157294:10;157269;:22;157280:10;157269:22;;;;;;;;;;;;;;;;:35;157261:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;157398:12;;;;;;;;;;;:25;;;157424:10;157444:4;157451:9;;157398:63;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;157376:127;;;;;;;;;;;;:::i;:::-;;;;;;;;;157516:15;157534:19;:17;:19::i;:::-;157516:37;;157564:30;157574:10;157586:7;157564:9;:30::i;:::-;157605:10;:22;157616:10;157605:22;;;;;;;;;;;;;;;;:24;;;;;;;;;:::i;:::-;;;;;;156952:685;;156927:710::o;126326:104::-;126378:7;126405:10;:17;;;;126398:24;;126326:104;:::o;158861:217::-;158978:10;158958:30;;:16;158966:7;158958;:16::i;:::-;:30;;;158950:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;159019:12;;;;;;;;;;;:28;;;159048:7;159057:12;159019:51;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158861:217;;:::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;155782:26::-;;;;;;;;;;;;;:::o;155459:42::-;;;:::o;111262:134::-;111349:39;111366:4;111372:2;111376:7;111349:39;;;;;;;;;;;;:16;:39::i;:::-;111262:134;;;:::o;159828:200::-;156284:8;;;;;;;;;;;156270:22;;:10;:22;;;156262:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;159933:1:::1;159907:28;;159915:5;159907:28;;::::0;159899:54:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;159964:5;:14;;;159979:8;;;;;;;;;;;159989:5;:15;;;160013:4;159989:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;159964:56;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;159828: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;155687:45::-;;;;;;;;;;;;;;;;;:::o;155562:24::-;;;;:::o;108575:120::-;108638:7;108665:22;108679:7;108665:13;:22::i;:::-;108658:29;;108575:120;;;:::o;156586:205::-;156284:8;;;;;;;;;;;156270:22;;:10;:22;;;156262:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;156678:9:::1;156673:111;156697:12;:19;156693:1;:23;156673:111;;;156768:4;156738:10;:27;156749:12;156762:1;156749:15;;;;;;;;:::i;:::-;;;;;;;;156738:27;;;;;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;156718:3;;;;;;;156673:111;;;;156586:205:::0;:::o;155815:24::-;;;;:::o;156339:123::-;156284:8;;;;;;;;;;;156270:22;;:10;:22;;;156262:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;156441:12:::1;156419;;:35;;;;;;;;;;;;;;;;;;156339: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;155508:47::-;155554:1;155508: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;157903:950::-;157968:13;158012:10;158002:7;:20;157994:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;158068:22;158093:12;;;;;;;;;;;:23;;;158117:7;158093:32;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;158068:57;;158136:20;158159:12;;;;;;;;;;;:22;;;158182:7;158159:31;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;158136:54;;158316:503;158458:17;158467:7;158458:8;:17::i;:::-;158658:30;158678:8;158658:13;:30::i;:::-;158739:6;158384:393;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;158316:13;:503::i;:::-;158231:603;;;;;;;;:::i;:::-;;;;;;;;;;;;;158203:642;;;;157903:950;;;:::o;155593: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;156473:105::-;156284:8;;;;;;;;;;;156270:22;;:10;:22;;;156262:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;156560:10:::1;156548:9;:22;;;;156473:105:::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;157645:250::-;157691:7;157731:1;157719:9;;:13;157711:36;;;;;;;;;;;;:::i;:::-;;;;;;;;;157758:13;157787:9;;157774:10;:22;;;;:::i;:::-;157758:38;;157807:15;157825;157834:5;157825:8;:15::i;:::-;157807:33;;157851:9;;:11;;;;;;;;;:::i;:::-;;;;;;157880:7;157873:14;;;;157645: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;159282:506::-;159338:13;159377:1;159368:5;:10;159364:26;;159380:10;;;;;;;;;;;;;;;;;;;;;159364:26;159401:12;159416:5;159401:20;;159432:14;159457:78;159472:1;159464:4;:9;159457:78;;159490:8;;;;;:::i;:::-;;;;159521:2;159513:10;;;;;:::i;:::-;;;159457:78;;;159545:19;159577:6;159567:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;159545:39;;159595:154;159611:1;159602:5;:10;159595:154;;159639:1;159629:11;;;;;:::i;:::-;;;159706:2;159698:5;:10;;;;:::i;:::-;159685:2;:24;;;;:::i;:::-;159672:39;;159655:6;159662;159655:14;;;;;;;;:::i;:::-;;;;;:56;;;;;;;;;;;159735:2;159726:11;;;;;:::i;:::-;;;159595:154;;;159773:6;159759:21;;;;;159282: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;159086:188::-;159142:7;159162:13;159178:4;159162:20;;159193:9;159228:1;159222;159214:5;:9;;;;:::i;:::-;159206:4;:18;;;;:::i;:::-;159205:24;;;;:::i;:::-;159193:36;;159261:5;159252;159248:1;:9;;;;:::i;:::-;159247:19;;;;:::i;:::-;159240:26;;;;159086: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:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:139::-;1887:6;1882:3;1877;1871:23;1928:1;1919:6;1914:3;1910:16;1903:27;1798:139;;;:::o;1943:102::-;1984:6;2035:2;2031:7;2026:2;2019:5;2015:14;2011:28;2001:38;;1943:102;;;:::o;2051:377::-;2139:3;2167:39;2200:5;2167:39;:::i;:::-;2222:71;2286:6;2281:3;2222:71;:::i;:::-;2215:78;;2302:65;2360:6;2355:3;2348:4;2341:5;2337:16;2302:65;:::i;:::-;2392:29;2414:6;2392:29;:::i;:::-;2387:3;2383:39;2376:46;;2143:285;2051:377;;;;:::o;2434:313::-;2547:4;2585:2;2574:9;2570:18;2562:26;;2634:9;2628:4;2624:20;2620:1;2609:9;2605:17;2598:47;2662:78;2735:4;2726:6;2662:78;:::i;:::-;2654:86;;2434:313;;;;:::o;2753:77::-;2790:7;2819:5;2808:16;;2753:77;;;:::o;2836:122::-;2909:24;2927:5;2909:24;:::i;:::-;2902:5;2899:35;2889:63;;2948:1;2945;2938:12;2889:63;2836:122;:::o;2964:139::-;3010:5;3048:6;3035:20;3026:29;;3064:33;3091:5;3064:33;:::i;:::-;2964:139;;;;:::o;3109:329::-;3168:6;3217:2;3205:9;3196:7;3192:23;3188:32;3185:119;;;3223:79;;:::i;:::-;3185:119;3343:1;3368:53;3413:7;3404:6;3393:9;3389:22;3368:53;:::i;:::-;3358:63;;3314:117;3109:329;;;;:::o;3444:126::-;3481:7;3521:42;3514:5;3510:54;3499:65;;3444:126;;;:::o;3576:96::-;3613:7;3642:24;3660:5;3642:24;:::i;:::-;3631:35;;3576:96;;;:::o;3678:118::-;3765:24;3783:5;3765:24;:::i;:::-;3760:3;3753:37;3678:118;;:::o;3802:222::-;3895:4;3933:2;3922:9;3918:18;3910:26;;3946:71;4014:1;4003:9;3999:17;3990:6;3946:71;:::i;:::-;3802:222;;;;:::o;4030:122::-;4103:24;4121:5;4103:24;:::i;:::-;4096:5;4093:35;4083:63;;4142:1;4139;4132:12;4083:63;4030:122;:::o;4158:139::-;4204:5;4242:6;4229:20;4220:29;;4258:33;4285:5;4258:33;:::i;:::-;4158:139;;;;:::o;4303:474::-;4371:6;4379;4428:2;4416:9;4407:7;4403:23;4399:32;4396:119;;;4434:79;;:::i;:::-;4396:119;4554:1;4579:53;4624:7;4615:6;4604:9;4600:22;4579:53;:::i;:::-;4569:63;;4525:117;4681:2;4707:53;4752:7;4743:6;4732:9;4728:22;4707:53;:::i;:::-;4697:63;;4652:118;4303:474;;;;;:::o;4783:329::-;4842:6;4891:2;4879:9;4870:7;4866:23;4862:32;4859:119;;;4897:79;;:::i;:::-;4859:119;5017:1;5042:53;5087:7;5078:6;5067:9;5063:22;5042:53;:::i;:::-;5032:63;;4988:117;4783:329;;;;:::o;5118:60::-;5146:3;5167:5;5160:12;;5118:60;;;:::o;5184:142::-;5234:9;5267:53;5285:34;5294:24;5312:5;5294:24;:::i;:::-;5285:34;:::i;:::-;5267:53;:::i;:::-;5254:66;;5184:142;;;:::o;5332:126::-;5382:9;5415:37;5446:5;5415:37;:::i;:::-;5402:50;;5332:126;;;:::o;5464:150::-;5538:9;5571:37;5602:5;5571:37;:::i;:::-;5558:50;;5464:150;;;:::o;5620:179::-;5731:61;5786:5;5731:61;:::i;:::-;5726:3;5719:74;5620:179;;:::o;5805:270::-;5922:4;5960:2;5949:9;5945:18;5937:26;;5973:95;6065:1;6054:9;6050:17;6041:6;5973:95;:::i;:::-;5805:270;;;;:::o;6081:118::-;6168:24;6186:5;6168:24;:::i;:::-;6163:3;6156:37;6081:118;;:::o;6205:222::-;6298:4;6336:2;6325:9;6321:18;6313:26;;6349:71;6417:1;6406:9;6402:17;6393:6;6349:71;:::i;:::-;6205:222;;;;:::o;6433:117::-;6542:1;6539;6532:12;6556:117;6665:1;6662;6655:12;6679:180;6727:77;6724:1;6717:88;6824:4;6821:1;6814:15;6848:4;6845:1;6838:15;6865:281;6948:27;6970:4;6948:27;:::i;:::-;6940:6;6936:40;7078:6;7066:10;7063:22;7042:18;7030:10;7027:34;7024:62;7021:88;;;7089:18;;:::i;:::-;7021:88;7129:10;7125:2;7118:22;6908:238;6865:281;;:::o;7152:129::-;7186:6;7213:20;;:::i;:::-;7203:30;;7242:33;7270:4;7262:6;7242:33;:::i;:::-;7152:129;;;:::o;7287:307::-;7348:4;7438:18;7430:6;7427:30;7424:56;;;7460:18;;:::i;:::-;7424:56;7498:29;7520:6;7498:29;:::i;:::-;7490:37;;7582:4;7576;7572:15;7564:23;;7287:307;;;:::o;7600:148::-;7698:6;7693:3;7688;7675:30;7739:1;7730:6;7725:3;7721:16;7714:27;7600:148;;;:::o;7754:423::-;7831:5;7856:65;7872:48;7913:6;7872:48;:::i;:::-;7856:65;:::i;:::-;7847:74;;7944:6;7937:5;7930:21;7982:4;7975:5;7971:16;8020:3;8011:6;8006:3;8002:16;7999:25;7996:112;;;8027:79;;:::i;:::-;7996:112;8117:54;8164:6;8159:3;8154;8117:54;:::i;:::-;7837:340;7754:423;;;;;:::o;8196:338::-;8251:5;8300:3;8293:4;8285:6;8281:17;8277:27;8267:122;;8308:79;;:::i;:::-;8267:122;8425:6;8412:20;8450:78;8524:3;8516:6;8509:4;8501:6;8497:17;8450:78;:::i;:::-;8441:87;;8257:277;8196:338;;;;:::o;8540:652::-;8617:6;8625;8674:2;8662:9;8653:7;8649:23;8645:32;8642:119;;;8680:79;;:::i;:::-;8642:119;8800:1;8825:53;8870:7;8861:6;8850:9;8846:22;8825:53;:::i;:::-;8815:63;;8771:117;8955:2;8944:9;8940:18;8927:32;8986:18;8978:6;8975:30;8972:117;;;9008:79;;:::i;:::-;8972:117;9113:62;9167:7;9158:6;9147:9;9143:22;9113:62;:::i;:::-;9103:72;;8898:287;8540:652;;;;;:::o;9198:619::-;9275:6;9283;9291;9340:2;9328:9;9319:7;9315:23;9311:32;9308:119;;;9346:79;;:::i;:::-;9308:119;9466:1;9491:53;9536:7;9527:6;9516:9;9512:22;9491:53;:::i;:::-;9481:63;;9437:117;9593:2;9619:53;9664:7;9655:6;9644:9;9640:22;9619:53;:::i;:::-;9609:63;;9564:118;9721:2;9747:53;9792:7;9783:6;9772:9;9768:22;9747:53;:::i;:::-;9737:63;;9692:118;9198:619;;;;;:::o;9823:141::-;9888:9;9921:37;9952:5;9921:37;:::i;:::-;9908:50;;9823:141;;;:::o;9970:161::-;10072:52;10118:5;10072:52;:::i;:::-;10067:3;10060:65;9970:161;;:::o;10137:252::-;10245:4;10283:2;10272:9;10268:18;10260:26;;10296:86;10379:1;10368:9;10364:17;10355:6;10296:86;:::i;:::-;10137:252;;;;:::o;10395:111::-;10447:7;10476:24;10494:5;10476:24;:::i;:::-;10465:35;;10395:111;;;:::o;10512:152::-;10600:39;10633:5;10600:39;:::i;:::-;10593:5;10590:50;10580:78;;10654:1;10651;10644:12;10580:78;10512:152;:::o;10670:169::-;10731:5;10769:6;10756:20;10747:29;;10785:48;10827:5;10785:48;:::i;:::-;10670:169;;;;:::o;10845:359::-;10919:6;10968:2;10956:9;10947:7;10943:23;10939:32;10936:119;;;10974:79;;:::i;:::-;10936:119;11094:1;11119:68;11179:7;11170:6;11159:9;11155:22;11119:68;:::i;:::-;11109:78;;11065:132;10845:359;;;;:::o;11210:311::-;11287:4;11377:18;11369:6;11366:30;11363:56;;;11399:18;;:::i;:::-;11363:56;11449:4;11441:6;11437:17;11429:25;;11509:4;11503;11499:15;11491:23;;11210:311;;;:::o;11527:117::-;11636:1;11633;11626:12;11667:710;11763:5;11788:81;11804:64;11861:6;11804:64;:::i;:::-;11788:81;:::i;:::-;11779:90;;11889:5;11918:6;11911:5;11904:21;11952:4;11945:5;11941:16;11934:23;;12005:4;11997:6;11993:17;11985:6;11981:30;12034:3;12026:6;12023:15;12020:122;;;12053:79;;:::i;:::-;12020:122;12168:6;12151:220;12185:6;12180:3;12177:15;12151:220;;;12260:3;12289:37;12322:3;12310:10;12289:37;:::i;:::-;12284:3;12277:50;12356:4;12351:3;12347:14;12340:21;;12227:144;12211:4;12206:3;12202:14;12195:21;;12151:220;;;12155:21;11769:608;;11667:710;;;;;:::o;12400:370::-;12471:5;12520:3;12513:4;12505:6;12501:17;12497:27;12487:122;;12528:79;;:::i;:::-;12487:122;12645:6;12632:20;12670:94;12760:3;12752:6;12745:4;12737:6;12733:17;12670:94;:::i;:::-;12661:103;;12477:293;12400:370;;;;:::o;12776:539::-;12860:6;12909:2;12897:9;12888:7;12884:23;12880:32;12877:119;;;12915:79;;:::i;:::-;12877:119;13063:1;13052:9;13048:17;13035:31;13093:18;13085:6;13082:30;13079:117;;;13115:79;;:::i;:::-;13079:117;13220:78;13290:7;13281:6;13270:9;13266:22;13220:78;:::i;:::-;13210:88;;13006:302;12776:539;;;;:::o;13321:116::-;13391:21;13406:5;13391:21;:::i;:::-;13384:5;13381:32;13371:60;;13427:1;13424;13417:12;13371:60;13321:116;:::o;13443:133::-;13486:5;13524:6;13511:20;13502:29;;13540:30;13564:5;13540:30;:::i;:::-;13443:133;;;;:::o;13582:468::-;13647:6;13655;13704:2;13692:9;13683:7;13679:23;13675:32;13672:119;;;13710:79;;:::i;:::-;13672:119;13830:1;13855:53;13900:7;13891:6;13880:9;13876:22;13855:53;:::i;:::-;13845:63;;13801:117;13957:2;13983:50;14025:7;14016:6;14005:9;14001:22;13983:50;:::i;:::-;13973:60;;13928:115;13582:468;;;;;:::o;14056:943::-;14151:6;14159;14167;14175;14224:3;14212:9;14203:7;14199:23;14195:33;14192:120;;;14231:79;;:::i;:::-;14192:120;14351:1;14376:53;14421:7;14412:6;14401:9;14397:22;14376:53;:::i;:::-;14366:63;;14322:117;14478:2;14504:53;14549:7;14540:6;14529:9;14525:22;14504:53;:::i;:::-;14494:63;;14449:118;14606:2;14632:53;14677:7;14668:6;14657:9;14653:22;14632:53;:::i;:::-;14622:63;;14577:118;14762:2;14751:9;14747:18;14734:32;14793:18;14785:6;14782:30;14779:117;;;14815:79;;:::i;:::-;14779:117;14920:62;14974:7;14965:6;14954:9;14950:22;14920:62;:::i;:::-;14910:72;;14705:287;14056:943;;;;;;;:::o;15005:104::-;15050:7;15079:24;15097:5;15079:24;:::i;:::-;15068:35;;15005:104;;;:::o;15115:142::-;15218:32;15244:5;15218:32;:::i;:::-;15213:3;15206:45;15115:142;;:::o;15263:254::-;15372:4;15410:2;15399:9;15395:18;15387:26;;15423:87;15507:1;15496:9;15492:17;15483:6;15423:87;:::i;:::-;15263:254;;;;:::o;15523:474::-;15591:6;15599;15648:2;15636:9;15627:7;15623:23;15619:32;15616:119;;;15654:79;;:::i;:::-;15616:119;15774:1;15799:53;15844:7;15835:6;15824:9;15820:22;15799:53;:::i;:::-;15789:63;;15745:117;15901:2;15927:53;15972:7;15963:6;15952:9;15948:22;15927:53;:::i;:::-;15917:63;;15872:118;15523:474;;;;;:::o;16003:180::-;16051:77;16048:1;16041:88;16148:4;16145:1;16138:15;16172:4;16169:1;16162:15;16189:320;16233:6;16270:1;16264:4;16260:12;16250:22;;16317:1;16311:4;16307:12;16338:18;16328:81;;16394:4;16386:6;16382:17;16372:27;;16328:81;16456:2;16448:6;16445:14;16425:18;16422:38;16419:84;;16475:18;;:::i;:::-;16419:84;16240:269;16189:320;;;:::o;16515:168::-;16655:20;16651:1;16643:6;16639:14;16632:44;16515:168;:::o;16689:366::-;16831:3;16852:67;16916:2;16911:3;16852:67;:::i;:::-;16845:74;;16928:93;17017:3;16928:93;:::i;:::-;17046:2;17041:3;17037:12;17030:19;;16689:366;;;:::o;17061:419::-;17227:4;17265:2;17254:9;17250:18;17242:26;;17314:9;17308:4;17304:20;17300:1;17289:9;17285:17;17278:47;17342:131;17468:4;17342:131;:::i;:::-;17334:139;;17061:419;;;:::o;17486:169::-;17626:21;17622:1;17614:6;17610:14;17603:45;17486:169;:::o;17661:366::-;17803:3;17824:67;17888:2;17883:3;17824:67;:::i;:::-;17817:74;;17900:93;17989:3;17900:93;:::i;:::-;18018:2;18013:3;18009:12;18002:19;;17661:366;;;:::o;18033:419::-;18199:4;18237:2;18226:9;18222:18;18214:26;;18286:9;18280:4;18276:20;18272:1;18261:9;18257:17;18250:47;18314:131;18440:4;18314:131;:::i;:::-;18306:139;;18033:419;;;:::o;18458:180::-;18506:77;18503:1;18496:88;18603:4;18600:1;18593:15;18627:4;18624:1;18617:15;18644:191;18684:3;18703:20;18721:1;18703:20;:::i;:::-;18698:25;;18737:20;18755:1;18737:20;:::i;:::-;18732:25;;18780:1;18777;18773:9;18766:16;;18801:3;18798:1;18795:10;18792:36;;;18808:18;;:::i;:::-;18792:36;18644:191;;;;:::o;18841:168::-;18981:20;18977:1;18969:6;18965:14;18958:44;18841:168;:::o;19015:366::-;19157:3;19178:67;19242:2;19237:3;19178:67;:::i;:::-;19171:74;;19254:93;19343:3;19254:93;:::i;:::-;19372:2;19367:3;19363:12;19356:19;;19015:366;;;:::o;19387:419::-;19553:4;19591:2;19580:9;19576:18;19568:26;;19640:9;19634:4;19630:20;19626:1;19615:9;19611:17;19604:47;19668:131;19794:4;19668:131;:::i;:::-;19660:139;;19387:419;;;:::o;19812:442::-;19961:4;19999:2;19988:9;19984:18;19976:26;;20012:71;20080:1;20069:9;20065:17;20056:6;20012:71;:::i;:::-;20093:72;20161:2;20150:9;20146:18;20137:6;20093:72;:::i;:::-;20175;20243:2;20232:9;20228:18;20219:6;20175:72;:::i;:::-;19812:442;;;;;;:::o;20260:137::-;20314:5;20345:6;20339:13;20330:22;;20361:30;20385:5;20361:30;:::i;:::-;20260:137;;;;:::o;20403:345::-;20470:6;20519:2;20507:9;20498:7;20494:23;20490:32;20487:119;;;20525:79;;:::i;:::-;20487:119;20645:1;20670:61;20723:7;20714:6;20703:9;20699:22;20670:61;:::i;:::-;20660:71;;20616:125;20403:345;;;;:::o;20754:164::-;20894:16;20890:1;20882:6;20878:14;20871:40;20754:164;:::o;20924:366::-;21066:3;21087:67;21151:2;21146:3;21087:67;:::i;:::-;21080:74;;21163:93;21252:3;21163:93;:::i;:::-;21281:2;21276:3;21272:12;21265:19;;20924:366;;;:::o;21296:419::-;21462:4;21500:2;21489:9;21485:18;21477:26;;21549:9;21543:4;21539:20;21535:1;21524:9;21520:17;21513:47;21577:131;21703:4;21577:131;:::i;:::-;21569:139;;21296:419;;;:::o;21721:233::-;21760:3;21783:24;21801:5;21783:24;:::i;:::-;21774:33;;21829:66;21822:5;21819:77;21816:103;;21899:18;;:::i;:::-;21816:103;21946:1;21939:5;21935:13;21928:20;;21721:233;;;:::o;21960:165::-;22100:17;22096:1;22088:6;22084:14;22077:41;21960:165;:::o;22131:366::-;22273:3;22294:67;22358:2;22353:3;22294:67;:::i;:::-;22287:74;;22370:93;22459:3;22370:93;:::i;:::-;22488:2;22483:3;22479:12;22472:19;;22131:366;;;:::o;22503:419::-;22669:4;22707:2;22696:9;22692:18;22684:26;;22756:9;22750:4;22746:20;22742:1;22731:9;22727:17;22720:47;22784:131;22910:4;22784:131;:::i;:::-;22776:139;;22503:419;;;:::o;22928:98::-;22979:6;23013:5;23007:12;22997:22;;22928:98;;;:::o;23032:168::-;23115:11;23149:6;23144:3;23137:19;23189:4;23184:3;23180:14;23165:29;;23032:168;;;;:::o;23206:373::-;23292:3;23320:38;23352:5;23320:38;:::i;:::-;23374:70;23437:6;23432:3;23374:70;:::i;:::-;23367:77;;23453:65;23511:6;23506:3;23499:4;23492:5;23488:16;23453:65;:::i;:::-;23543:29;23565:6;23543:29;:::i;:::-;23538:3;23534:39;23527:46;;23296:283;23206:373;;;;:::o;23585:419::-;23724:4;23762:2;23751:9;23747:18;23739:26;;23775:71;23843:1;23832:9;23828:17;23819:6;23775:71;:::i;:::-;23893:9;23887:4;23883:20;23878:2;23867:9;23863:18;23856:48;23921:76;23992:4;23983:6;23921:76;:::i;:::-;23913:84;;23585:419;;;;;:::o;24010:442::-;24159:4;24197:2;24186:9;24182:18;24174:26;;24210:71;24278:1;24267:9;24263:17;24254:6;24210:71;:::i;:::-;24291:72;24359:2;24348:9;24344:18;24335:6;24291:72;:::i;:::-;24373;24441:2;24430:9;24426:18;24417:6;24373:72;:::i;:::-;24010:442;;;;;;:::o;24458:332::-;24579:4;24617:2;24606:9;24602:18;24594:26;;24630:71;24698:1;24687:9;24683:17;24674:6;24630:71;:::i;:::-;24711:72;24779:2;24768:9;24764:18;24755:6;24711:72;:::i;:::-;24458:332;;;;;:::o;24796:164::-;24936:16;24932:1;24924:6;24920:14;24913:40;24796:164;:::o;24966:366::-;25108:3;25129:67;25193:2;25188:3;25129:67;:::i;:::-;25122:74;;25205:93;25294:3;25205:93;:::i;:::-;25323:2;25318:3;25314:12;25307:19;;24966:366;;;:::o;25338:419::-;25504:4;25542:2;25531:9;25527:18;25519:26;;25591:9;25585:4;25581:20;25577:1;25566:9;25562:17;25555:47;25619:131;25745:4;25619:131;:::i;:::-;25611:139;;25338:419;;;:::o;25763:163::-;25903:15;25899:1;25891:6;25887:14;25880:39;25763:163;:::o;25932:366::-;26074:3;26095:67;26159:2;26154:3;26095:67;:::i;:::-;26088:74;;26171:93;26260:3;26171:93;:::i;:::-;26289:2;26284:3;26280:12;26273:19;;25932:366;;;:::o;26304:419::-;26470:4;26508:2;26497:9;26493:18;26485:26;;26557:9;26551:4;26547:20;26543:1;26532:9;26528:17;26521:47;26585:131;26711:4;26585:131;:::i;:::-;26577:139;;26304:419;;;:::o;26729:143::-;26786:5;26817:6;26811:13;26802:22;;26833:33;26860:5;26833:33;:::i;:::-;26729:143;;;;:::o;26878:351::-;26948:6;26997:2;26985:9;26976:7;26972:23;26968:32;26965:119;;;27003:79;;:::i;:::-;26965:119;27123:1;27148:64;27204:7;27195:6;27184:9;27180:22;27148:64;:::i;:::-;27138:74;;27094:128;26878:351;;;;:::o;27235:134::-;27293:9;27326:37;27357:5;27326:37;:::i;:::-;27313:50;;27235:134;;;:::o;27375:147::-;27470:45;27509:5;27470:45;:::i;:::-;27465:3;27458:58;27375:147;;:::o;27528:348::-;27657:4;27695:2;27684:9;27680:18;27672:26;;27708:79;27784:1;27773:9;27769:17;27760:6;27708:79;:::i;:::-;27797:72;27865:2;27854:9;27850:18;27841:6;27797:72;:::i;:::-;27528:348;;;;;:::o;27882:180::-;27930:77;27927:1;27920:88;28027:4;28024:1;28017:15;28051:4;28048:1;28041:15;28068:170;28208:22;28204:1;28196:6;28192:14;28185:46;28068:170;:::o;28244:366::-;28386:3;28407:67;28471:2;28466:3;28407:67;:::i;:::-;28400:74;;28483:93;28572:3;28483:93;:::i;:::-;28601:2;28596:3;28592:12;28585:19;;28244:366;;;:::o;28616:419::-;28782:4;28820:2;28809:9;28805:18;28797:26;;28869:9;28863:4;28859:20;28855:1;28844:9;28840:17;28833:47;28897:131;29023:4;28897:131;:::i;:::-;28889:139;;28616:419;;;:::o;29041:308::-;29103:4;29193:18;29185:6;29182:30;29179:56;;;29215:18;;:::i;:::-;29179:56;29253:29;29275:6;29253:29;:::i;:::-;29245:37;;29337:4;29331;29327:15;29319:23;;29041:308;;;:::o;29355:434::-;29444:5;29469:66;29485:49;29527:6;29485:49;:::i;:::-;29469:66;:::i;:::-;29460:75;;29558:6;29551:5;29544:21;29596:4;29589:5;29585:16;29634:3;29625:6;29620:3;29616:16;29613:25;29610:112;;;29641:79;;:::i;:::-;29610:112;29731:52;29776:6;29771:3;29766;29731:52;:::i;:::-;29450:339;29355:434;;;;;:::o;29809:355::-;29876:5;29925:3;29918:4;29910:6;29906:17;29902:27;29892:122;;29933:79;;:::i;:::-;29892:122;30043:6;30037:13;30068:90;30154:3;30146:6;30139:4;30131:6;30127:17;30068:90;:::i;:::-;30059:99;;29882:282;29809:355;;;;:::o;30170:524::-;30250:6;30299:2;30287:9;30278:7;30274:23;30270:32;30267:119;;;30305:79;;:::i;:::-;30267:119;30446:1;30435:9;30431:17;30425:24;30476:18;30468:6;30465:30;30462:117;;;30498:79;;:::i;:::-;30462:117;30603:74;30669:7;30660:6;30649:9;30645:22;30603:74;:::i;:::-;30593:84;;30396:291;30170:524;;;;:::o;30700:148::-;30802:11;30839:3;30824:18;;30700:148;;;;:::o;30854:214::-;30994:66;30990:1;30982:6;30978:14;30971:90;30854:214;:::o;31074:402::-;31234:3;31255:85;31337:2;31332:3;31255:85;:::i;:::-;31248:92;;31349:93;31438:3;31349:93;:::i;:::-;31467:2;31462:3;31458:12;31451:19;;31074:402;;;:::o;31482:390::-;31588:3;31616:39;31649:5;31616:39;:::i;:::-;31671:89;31753:6;31748:3;31671:89;:::i;:::-;31664:96;;31769:65;31827:6;31822:3;31815:4;31808:5;31804:16;31769:65;:::i;:::-;31859:6;31854:3;31850:16;31843:23;;31592:280;31482:390;;;;:::o;31878:384::-;32018:66;32014:1;32006:6;32002:14;31995:90;32119:34;32114:2;32106:6;32102:15;32095:59;32188:66;32183:2;32175:6;32171:15;32164:91;31878:384;:::o;32268:402::-;32428:3;32449:85;32531:2;32526:3;32449:85;:::i;:::-;32442:92;;32543:93;32632:3;32543:93;:::i;:::-;32661:2;32656:3;32652:12;32645:19;;32268:402;;;:::o;32676:254::-;32816:66;32812:1;32804:6;32800:14;32793:90;32917:5;32912:2;32904:6;32900:15;32893:30;32676:254;:::o;32936:402::-;33096:3;33117:85;33199:2;33194:3;33117:85;:::i;:::-;33110:92;;33211:93;33300:3;33211:93;:::i;:::-;33329:2;33324:3;33320:12;33313:19;;32936:402;;;:::o;33344:214::-;33484:66;33480:1;33472:6;33468:14;33461:90;33344:214;:::o;33564:402::-;33724:3;33745:85;33827:2;33822:3;33745:85;:::i;:::-;33738:92;;33839:93;33928:3;33839:93;:::i;:::-;33957:2;33952:3;33948:12;33941:19;;33564:402;;;:::o;33972:143::-;34108:3;34104:1;34096:6;34092:14;34085:27;33972:143;:::o;34117:384::-;34277:3;34294:84;34376:1;34371:3;34294:84;:::i;:::-;34287:91;;34383:93;34472:3;34383:93;:::i;:::-;34497:1;34492:3;34488:11;34481:18;;34117:384;;;:::o;34503:1885::-;35236:3;35254:148;35398:3;35254:148;:::i;:::-;35247:155;;35415:95;35506:3;35497:6;35415:95;:::i;:::-;35408:102;;35523:148;35667:3;35523:148;:::i;:::-;35516:155;;35684:148;35828:3;35684:148;:::i;:::-;35677:155;;35845:95;35936:3;35927:6;35845:95;:::i;:::-;35838:102;;35953:148;36097:3;35953:148;:::i;:::-;35946:155;;36114:95;36205:3;36196:6;36114:95;:::i;:::-;36107:102;;36222:148;36366:3;36222:148;:::i;:::-;36215:155;;36383:3;36376:10;;34503:1885;;;;;;:::o;36390:171::-;36526:31;36522:1;36514:6;36510:14;36503:55;36390:171;:::o;36563:386::-;36723:3;36740:85;36822:2;36817:3;36740:85;:::i;:::-;36733:92;;36830:93;36919:3;36830:93;:::i;:::-;36944:2;36939:3;36935:12;36928:19;;36563:386;;;:::o;36951:525::-;37184:3;37202:148;37346:3;37202:148;:::i;:::-;37195:155;;37363:95;37454:3;37445:6;37363:95;:::i;:::-;37356:102;;37471:3;37464:10;;36951:525;;;;:::o;37478:152::-;37614:12;37610:1;37602:6;37598:14;37591:36;37478:152;:::o;37632:350::-;37774:3;37791:67;37855:2;37850:3;37791:67;:::i;:::-;37784:74;;37863:93;37952:3;37863:93;:::i;:::-;37977:2;37972:3;37968:12;37961:19;;37632:350;;;:::o;37984:403::-;38150:4;38184:2;38173:9;38169:18;38161:26;;38229:9;38223:4;38219:20;38215:1;38204:9;38200:17;38193:47;38253:131;38379:4;38253:131;:::i;:::-;38245:139;;37984:403;;;:::o;38389:174::-;38429:4;38445:20;38463:1;38445:20;:::i;:::-;38440:25;;38475:20;38493:1;38475:20;:::i;:::-;38470:25;;38515:1;38512;38508:9;38500:17;;38535:1;38529:4;38526:11;38523:37;;;38540:18;;:::i;:::-;38523:37;38389:174;;;;:::o;38565:155::-;38604:3;38623:24;38641:5;38623:24;:::i;:::-;38614:33;;38665:4;38658:5;38655:15;38652:41;;38673:18;;:::i;:::-;38652:41;38716:1;38709:5;38705:13;38698:20;;38565:155;;;:::o;38722:612::-;38917:4;38951:3;38940:9;38936:19;38928:27;;38961:71;39029:1;39018:9;39014:17;39005:6;38961:71;:::i;:::-;39038:72;39106:2;39095:9;39091:18;39082:6;39038:72;:::i;:::-;39116;39184:2;39173:9;39169:18;39160:6;39116:72;:::i;:::-;39231:9;39225:4;39221:20;39216:2;39205:9;39201:18;39194:48;39255:76;39326:4;39317:6;39255:76;:::i;:::-;39247:84;;38722:612;;;;;;;:::o;39336:129::-;39392:5;39419:6;39413:13;39404:22;;39431:32;39457:5;39431:32;:::i;:::-;39336:129;;;;:::o;39467:325::-;39536:6;39581:2;39569:9;39560:7;39556:23;39552:32;39549:119;;;39587:79;;:::i;:::-;39549:119;39699:1;39720:63;39775:7;39766:6;39755:9;39751:22;39720:63;:::i;:::-;39710:73;;39674:115;39467:325;;;;:::o;39794:164::-;39838:77;39835:1;39828:88;39931:4;39928:1;39921:15;39951:4;39948:1;39941:15;39960:165;40000:1;40013:20;40031:1;40013:20;:::i;:::-;40008:25;;40043:20;40061:1;40043:20;:::i;:::-;40038:25;;40078:1;40068:35;;40083:18;;:::i;:::-;40068:35;40121:1;40118;40114:9;40109:14;;39960:165;;;;:::o;40127:156::-;40159:1;40172:20;40190:1;40172:20;:::i;:::-;40167:25;;40202:20;40220:1;40202:20;:::i;:::-;40197:25;;40237:1;40227:35;;40242:18;;:::i;:::-;40227:35;40279:1;40276;40272:9;40267:14;;40127:156;;;;:::o;40285:362::-;40325:7;40344:20;40362:1;40344:20;:::i;:::-;40339:25;;40374:20;40392:1;40374:20;:::i;:::-;40369:25;;40425:1;40422;40418:9;40443:30;40461:11;40443:30;:::i;:::-;40432:41;;40602:1;40593:7;40589:15;40586:1;40583:22;40567:1;40560:9;40544:71;40525:119;;40624:18;;:::i;:::-;40525:119;40333:314;40285:362;;;;:::o;40649:164::-;40693:77;40690:1;40683:88;40786:4;40783:1;40776:15;40806:4;40803:1;40796:15
Swarm Source
ipfs://b80c746532ce4709106d1b25805f4f2252f41c70c34710f940ddb06948d07ecd
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.