Overview
TokenID
2392
Total Transfers
-
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
OCSpikiesRandom
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity)
/** *Submitted for verification at apescan.io on 2025-03-09 */ // SPDX-License-Identifier: MIT // 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/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/interfaces/IERC2981.sol // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.20; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. * * NOTE: ERC-2981 allows setting the royalty to 100% of the price. In that case all the price would be sent to the * royalty receiver and 0 tokens to the seller. Contracts dealing with royalty should consider empty transfers. */ function royaltyInfo( uint256 tokenId, uint256 salePrice ) external view returns (address receiver, uint256 royaltyAmount); } // File: @openzeppelin/contracts/token/common/ERC2981.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/common/ERC2981.sol) pragma solidity ^0.8.20; /** * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information. * * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first. * * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the * fee is specified in basis points by default. * * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the ERC. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. */ abstract contract ERC2981 is IERC2981, ERC165 { struct RoyaltyInfo { address receiver; uint96 royaltyFraction; } RoyaltyInfo private _defaultRoyaltyInfo; mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo; /** * @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1). */ error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator); /** * @dev The default royalty receiver is invalid. */ error ERC2981InvalidDefaultRoyaltyReceiver(address receiver); /** * @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1). */ error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator); /** * @dev The royalty receiver for `tokenId` is invalid. */ error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver); /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc IERC2981 */ function royaltyInfo( uint256 tokenId, uint256 salePrice ) public view virtual returns (address receiver, uint256 amount) { RoyaltyInfo storage _royaltyInfo = _tokenRoyaltyInfo[tokenId]; address royaltyReceiver = _royaltyInfo.receiver; uint96 royaltyFraction = _royaltyInfo.royaltyFraction; if (royaltyReceiver == address(0)) { royaltyReceiver = _defaultRoyaltyInfo.receiver; royaltyFraction = _defaultRoyaltyInfo.royaltyFraction; } uint256 royaltyAmount = (salePrice * royaltyFraction) / _feeDenominator(); return (royaltyReceiver, royaltyAmount); } /** * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an * override. */ function _feeDenominator() internal pure virtual returns (uint96) { return 10000; } /** * @dev Sets the royalty information that all ids in this contract will default to. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { uint256 denominator = _feeDenominator(); if (feeNumerator > denominator) { // Royalty fee will exceed the sale price revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator); } if (receiver == address(0)) { revert ERC2981InvalidDefaultRoyaltyReceiver(address(0)); } _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Removes default royalty information. */ function _deleteDefaultRoyalty() internal virtual { delete _defaultRoyaltyInfo; } /** * @dev Sets the royalty information for a specific token id, overriding the global default. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual { uint256 denominator = _feeDenominator(); if (feeNumerator > denominator) { // Royalty fee will exceed the sale price revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator); } if (receiver == address(0)) { revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0)); } _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Resets royalty information for the token id back to the global default. */ function _resetTokenRoyalty(uint256 tokenId) internal virtual { delete _tokenRoyaltyInfo[tokenId]; } } // File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Royalty.sol) pragma solidity ^0.8.20; /** * @dev Extension of ERC-721 with the ERC-2981 NFT Royalty Standard, a standardized way to retrieve royalty payment * information. * * Royalty information can be specified globally for all token ids via {ERC2981-_setDefaultRoyalty}, and/or individually * for specific token ids via {ERC2981-_setTokenRoyalty}. The latter takes precedence over the first. * * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the ERC. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. */ abstract contract ERC721Royalty is ERC2981, ERC721 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) { return super.supportsInterface(interfaceId); } } // 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/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/OCSpikiesRandom.sol pragma solidity ^0.8.20; interface ISpikiesDataSource { function getLayerSVG(uint8 layerId, uint256 traitId) external view returns (string memory); function getLayerTrait(uint8 layerId, uint256 traitId) external view returns (string memory); function getLayerCount(uint8 layerId) external pure returns (uint256); } contract OCSpikiesRandom is ERC721, ERC721Royalty, Ownable { ISpikiesDataSource public dataSource; uint256 public totalSupply; uint256 public constant MAX_SUPPLY = 5555; // Max 5,555 NFTs uint256 public constant MAX_BATCH_SIZE = 505; struct Traits { uint256 eyes; uint256 heads; uint256 mouths; } mapping(uint256 => Traits) public tokenTraits; mapping(bytes32 => bool) public usedCombinations; mapping(address => uint256) public nonces; constructor(address _dataSource, address royaltyReceiver) ERC721("OCSpikies", "OCS") Ownable(msg.sender) { dataSource = ISpikiesDataSource(_dataSource); _setDefaultRoyalty(royaltyReceiver, 690); } function mintRandom(address to) external onlyOwner returns (uint256) { require(totalSupply < MAX_SUPPLY, "Max supply reached"); nonces[msg.sender]++; uint256 attempt = 0; bool found = false; uint256 eyesTraitId; uint256 headsTraitId; uint256 mouthsTraitId; while (!found && attempt < 10) { uint256 seed = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), msg.sender, nonces[msg.sender], attempt))); uint256 eyesSeed = uint256(keccak256(abi.encodePacked(seed, "eyes"))); uint256 headsSeed = uint256(keccak256(abi.encodePacked(seed, "heads"))); uint256 mouthsSeed = uint256(keccak256(abi.encodePacked(seed, "mouths"))); eyesTraitId = eyesSeed % 143; headsTraitId = headsSeed % 86; mouthsTraitId = mouthsSeed % 13; bytes32 comboHash = keccak256(abi.encodePacked(eyesTraitId, headsTraitId, mouthsTraitId)); if (!usedCombinations[comboHash]) { usedCombinations[comboHash] = true; found = true; } else { attempt++; } } require(found, "No unique combination found after 10 attempts"); totalSupply++; uint256 tokenId = totalSupply; tokenTraits[tokenId] = Traits(eyesTraitId, headsTraitId, mouthsTraitId); _mint(to, tokenId); return tokenId; } //Batch minting subroutine function mintRandomBatch(address to, uint256 quantity) external onlyOwner returns (uint256[] memory) { require(quantity > 0 && quantity <= MAX_BATCH_SIZE, "Quantity must be between 1 and 505"); require(totalSupply + quantity <= MAX_SUPPLY, "Batch mint would exceed max supply"); uint256[] memory tokenIds = new uint256[](quantity); for (uint256 i = 0; i < quantity; i++) { nonces[msg.sender]++; uint256 attempt = 0; bool found = false; uint256 eyesTraitId; uint256 headsTraitId; uint256 mouthsTraitId; while (!found && attempt < 10) { uint256 seed = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), msg.sender, nonces[msg.sender], attempt))); uint256 eyesSeed = uint256(keccak256(abi.encodePacked(seed, "eyes"))); uint256 headsSeed = uint256(keccak256(abi.encodePacked(seed, "heads"))); uint256 mouthsSeed = uint256(keccak256(abi.encodePacked(seed, "mouths"))); eyesTraitId = eyesSeed % 143; headsTraitId = headsSeed % 86; mouthsTraitId = mouthsSeed % 13; bytes32 comboHash = keccak256(abi.encodePacked(eyesTraitId, headsTraitId, mouthsTraitId)); if (!usedCombinations[comboHash]) { usedCombinations[comboHash] = true; found = true; } else { attempt++; } } require(found, "No unique combination found after 10 attempts"); totalSupply++; uint256 tokenId = totalSupply; tokenTraits[tokenId] = Traits(eyesTraitId, headsTraitId, mouthsTraitId); _mint(to, tokenId); tokenIds[i] = tokenId; } return tokenIds; } function tokenURI(uint256 tokenId) public view override returns (string memory) { ownerOf(tokenId); // Reverts if token doesn't exist Traits memory traits = tokenTraits[tokenId]; uint256 bgTraitId = 0; uint256 eyesTraitId = traits.eyes; uint256 headsTraitId = traits.heads; uint256 mouthsTraitId = traits.mouths; string memory svg = _buildSVG(bgTraitId, eyesTraitId, headsTraitId, mouthsTraitId); string memory traitsJson = _buildTraits(bgTraitId, eyesTraitId, headsTraitId, mouthsTraitId); string memory json = string(abi.encodePacked( '{"name":"Spiky #', toString(tokenId), '",', '"description":"An on-chain implementation of Spikies NFT on ApeChain. OCSpikies are Dark mode On-Chain variants of Spikies NFT",', '"image":"data:image/svg+xml;base64,', Base64.encode(bytes(svg)), '",', '"attributes":[', traitsJson, ']}' )); return string(abi.encodePacked("data:application/json;base64,", Base64.encode(bytes(json)))); } function _buildSVG( uint256 bgTraitId, uint256 eyesTraitId, uint256 headsTraitId, uint256 mouthsTraitId ) internal view returns (string memory) { string memory bgSVG = dataSource.getLayerSVG(0, bgTraitId); string memory mouthsSVG = dataSource.getLayerSVG(5, mouthsTraitId); string memory eyesSVG = dataSource.getLayerSVG(3, eyesTraitId); string memory headsSVG = dataSource.getLayerSVG(4, headsTraitId); return string(abi.encodePacked( '<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512">', bgSVG, mouthsSVG, eyesSVG, headsSVG, '</svg>' )); } function _buildTraits( uint256 bgTraitId, uint256 eyesTraitId, uint256 headsTraitId, uint256 mouthsTraitId ) internal view returns (string memory) { string memory traits = dataSource.getLayerTrait(0, bgTraitId); traits = string(abi.encodePacked(traits, ",", dataSource.getLayerTrait(3, eyesTraitId))); traits = string(abi.encodePacked(traits, ",", dataSource.getLayerTrait(4, headsTraitId))); traits = string(abi.encodePacked(traits, ",", dataSource.getLayerTrait(5, mouthsTraitId))); return traits; } 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--; buffer[digits] = bytes1(uint8(48 + (value % 10))); value /= 10; } return string(buffer); } // Function to withdraw ERC20 tokens function withdrawERC20(address tokenAddress) external onlyOwner { IERC20 token = IERC20(tokenAddress); uint256 balance = token.balanceOf(address(this)); require(balance > 0, "No tokens to withdraw"); token.transfer(owner(), balance); } // Function to withdraw balance function withdrawETH() external onlyOwner { uint256 balance = address(this).balance; require(balance > 0, "No ETH to withdraw"); payable(owner()).transfer(balance); } // Override required by ERC721Royalty and ERC721 to support multiple inheritance function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721Royalty) returns (bool) { return super.supportsInterface(interfaceId); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_dataSource","type":"address"},{"internalType":"address","name":"royaltyReceiver","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","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"}],"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":"MAX_BATCH_SIZE","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":"dataSource","outputs":[{"internalType":"contract ISpikiesDataSource","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":"to","type":"address"}],"name":"mintRandom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mintRandomBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","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":"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":"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":"","type":"uint256"}],"name":"tokenTraits","outputs":[{"internalType":"uint256","name":"eyes","type":"uint256"},{"internalType":"uint256","name":"heads","type":"uint256"},{"internalType":"uint256","name":"mouths","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":"bytes32","name":"","type":"bytes32"}],"name":"usedCombinations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561000f575f5ffd5b50604051614e0b380380614e0b83398181016040528101906100319190610463565b336040518060400160405280600981526020017f4f435370696b69657300000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f4f4353000000000000000000000000000000000000000000000000000000000081525081600290816100ad91906106de565b5080600390816100bd91906106de565b5050505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610130575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161012791906107bc565b60405180910390fd5b61013f8161019960201b60201c565b508160095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610192816102b261025c60201b60201c565b5050610852565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f61026b6103fc60201b60201c565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156102d05781816040517f6f483d090000000000000000000000000000000000000000000000000000000081526004016102c792919061082b565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610340575f6040517fb6d9900a00000000000000000000000000000000000000000000000000000000815260040161033791906107bc565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff168152505f5f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f612710905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61043282610409565b9050919050565b61044281610428565b811461044c575f5ffd5b50565b5f8151905061045d81610439565b92915050565b5f5f6040838503121561047957610478610405565b5b5f6104868582860161044f565b92505060206104978582860161044f565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061051c57607f821691505b60208210810361052f5761052e6104d8565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026105917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610556565b61059b8683610556565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6105df6105da6105d5846105b3565b6105bc565b6105b3565b9050919050565b5f819050919050565b6105f8836105c5565b61060c610604826105e6565b848454610562565b825550505050565b5f5f905090565b610623610614565b61062e8184846105ef565b505050565b5b81811015610651576106465f8261061b565b600181019050610634565b5050565b601f8211156106965761066781610535565b61067084610547565b8101602085101561067f578190505b61069361068b85610547565b830182610633565b50505b505050565b5f82821c905092915050565b5f6106b65f198460080261069b565b1980831691505092915050565b5f6106ce83836106a7565b9150826002028217905092915050565b6106e7826104a1565b67ffffffffffffffff811115610700576106ff6104ab565b5b61070a8254610505565b610715828285610655565b5f60209050601f831160018114610746575f8415610734578287015190505b61073e85826106c3565b8655506107a5565b601f19841661075486610535565b5f5b8281101561077b57848901518255600182019150602085019450602081019050610756565b868310156107985784890151610794601f8916826106a7565b8355505b6001600288020188555050505b505050505050565b6107b681610428565b82525050565b5f6020820190506107cf5f8301846107ad565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b5f6108066108016107fc846107d5565b6105bc565b6105b3565b9050919050565b610816816107ec565b82525050565b610825816105b3565b82525050565b5f60408201905061083e5f83018561080d565b61084b602083018461081c565b9392505050565b6145ac8061085f5f395ff3fe608060405234801561000f575f5ffd5b50600436106101c2575f3560e01c80637ecebe00116100f7578063d023f37e11610095578063e086e5ec1161006f578063e086e5ec14610541578063e985e9c51461054b578063f2fde38b1461057b578063f4f3b20014610597576101c2565b8063d023f37e146104af578063d1cea4ec146104df578063e05c57bf1461050f576101c2565b8063a22cb465116100d1578063a22cb46514610429578063b88d4fde14610445578063c87b56dd14610461578063cfdbf25414610491576101c2565b80637ecebe00146103bd5780638da5cb5b146103ed57806395d89b411461040b576101c2565b80632a55205a1161016457806349bc4aed1161013e57806349bc4aed146103235780636352211e1461035357806370a0823114610383578063715018a6146103b3576101c2565b80632a55205a146102b857806332cb6b0c146102e957806342842e0e14610307576101c2565b8063095ea7b3116101a0578063095ea7b31461024457806318160ddd146102605780631b076edc1461027e57806323b872dd1461029c576101c2565b806301ffc9a7146101c657806306fdde03146101f6578063081812fc14610214575b5f5ffd5b6101e060048036038101906101db9190612d3c565b6105b3565b6040516101ed9190612d81565b60405180910390f35b6101fe6105c4565b60405161020b9190612e0a565b60405180910390f35b61022e60048036038101906102299190612e5d565b610654565b60405161023b9190612ec7565b60405180910390f35b61025e60048036038101906102599190612f0a565b61066f565b005b610268610685565b6040516102759190612f57565b60405180910390f35b61028661068b565b6040516102939190612fcb565b60405180910390f35b6102b660048036038101906102b19190612fe4565b6106b0565b005b6102d260048036038101906102cd9190613034565b6107af565b6040516102e0929190613072565b60405180910390f35b6102f16108cf565b6040516102fe9190612f57565b60405180910390f35b610321600480360381019061031c9190612fe4565b6108d5565b005b61033d600480360381019061033891906130cc565b6108f4565b60405161034a9190612d81565b60405180910390f35b61036d60048036038101906103689190612e5d565b610911565b60405161037a9190612ec7565b60405180910390f35b61039d600480360381019061039891906130f7565b610922565b6040516103aa9190612f57565b60405180910390f35b6103bb6109d8565b005b6103d760048036038101906103d291906130f7565b6109eb565b6040516103e49190612f57565b60405180910390f35b6103f5610a00565b6040516104029190612ec7565b60405180910390f35b610413610a28565b6040516104209190612e0a565b60405180910390f35b610443600480360381019061043e919061314c565b610ab8565b005b61045f600480360381019061045a91906132b6565b610ace565b005b61047b60048036038101906104769190612e5d565b610af3565b6040516104889190612e0a565b60405180910390f35b610499610be2565b6040516104a69190612f57565b60405180910390f35b6104c960048036038101906104c49190612f0a565b610be8565b6040516104d691906133ed565b60405180910390f35b6104f960048036038101906104f491906130f7565b611016565b6040516105069190612f57565b60405180910390f35b61052960048036038101906105249190612e5d565b61135e565b6040516105389392919061340d565b60405180910390f35b610549611384565b005b61056560048036038101906105609190613442565b611420565b6040516105729190612d81565b60405180910390f35b610595600480360381019061059091906130f7565b6114ae565b005b6105b160048036038101906105ac91906130f7565b611532565b005b5f6105bd82611683565b9050919050565b6060600280546105d3906134ad565b80601f01602080910402602001604051908101604052809291908181526020018280546105ff906134ad565b801561064a5780601f106106215761010080835404028352916020019161064a565b820191905f5260205f20905b81548152906001019060200180831161062d57829003601f168201915b5050505050905090565b5f61065e82611694565b506106688261171a565b9050919050565b610681828261067c611753565b61175a565b5050565b600a5481565b60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610720575f6040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016107179190612ec7565b60405180910390fd5b5f610733838361072e611753565b61176c565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146107a9578382826040517f64283d7b0000000000000000000000000000000000000000000000000000000081526004016107a0939291906134dd565b60405180910390fd5b50505050565b5f5f5f60015f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610881575f5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505f5f0160149054906101000a90046bffffffffffffffffffffffff1690505b5f61088a611977565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff16886108b2919061353f565b6108bc91906135ad565b9050828195509550505050509250929050565b6115b381565b6108ef83838360405180602001604052805f815250610ace565b505050565b600c602052805f5260405f205f915054906101000a900460ff1681565b5f61091b82611694565b9050919050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610993575f6040517f89c62b6400000000000000000000000000000000000000000000000000000000815260040161098a9190612ec7565b60405180910390fd5b60055f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6109e0611980565b6109e95f611a07565b565b600d602052805f5260405f205f915090505481565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060038054610a37906134ad565b80601f0160208091040260200160405190810160405280929190818152602001828054610a63906134ad565b8015610aae5780601f10610a8557610100808354040283529160200191610aae565b820191905f5260205f20905b815481529060010190602001808311610a9157829003601f168201915b5050505050905090565b610aca610ac3611753565b8383611aca565b5050565b610ad98484846106b0565b610aed610ae4611753565b85858585611c33565b50505050565b6060610afe82610911565b505f600b5f8481526020019081526020015f206040518060600160405290815f82015481526020016001820154815260200160028201548152505090505f5f90505f825f015190505f836020015190505f846040015190505f610b6385858585611ddf565b90505f610b728686868661209c565b90505f610b7e8a612391565b610b87846124e9565b83604051602001610b9a9392919061386b565b6040516020818303038152906040529050610bb4816124e9565b604051602001610bc49190613932565b60405160208183030381529060405298505050505050505050919050565b6101f981565b6060610bf2611980565b5f82118015610c0357506101f98211155b610c42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c39906139c3565b60405180910390fd5b6115b382600a54610c5391906139e1565b1115610c94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8b90613a84565b60405180910390fd5b5f8267ffffffffffffffff811115610caf57610cae613192565b5b604051908082528060200260200182016040528015610cdd5781602001602082028036833780820191505090505b5090505f5f90505b8381101561100b57600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610d3a90613aa2565b91905055505f5f90505f5f90505f5f5f5b83158015610d595750600a85105b15610f26575f600143610d6c9190613ae9565b4033600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205488604051602001610dc09493929190613ba1565b604051602081830303815290604052805190602001205f1c90505f81604051602001610dec9190613c38565b604051602081830303815290604052805190602001205f1c90505f82604051602001610e189190613ca7565b604051602081830303815290604052805190602001205f1c90505f83604051602001610e449190613d16565b604051602081830303815290604052805190602001205f1c9050608f83610e6b9190613d3b565b9650605682610e7a9190613d3b565b9550600d81610e899190613d3b565b94505f878787604051602001610ea193929190613d6b565b604051602081830303815290604052805190602001209050600c5f8281526020019081526020015f205f9054906101000a900460ff16610f0d576001600c5f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555060019850610f1c565b8980610f1890613aa2565b9a50505b5050505050610d4b565b83610f66576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5d90613e17565b60405180910390fd5b600a5f815480929190610f7890613aa2565b91905055505f600a549050604051806060016040528085815260200184815260200183815250600b5f8381526020019081526020015f205f820151815f01556020820151816001015560408201518160020155905050610fd88b82612516565b80888881518110610fec57610feb613e35565b5b6020026020010181815250505050505050508080600101915050610ce5565b508091505092915050565b5f61101f611980565b6115b3600a5410611065576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105c90613eac565b60405180910390fd5b600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154809291906110b290613aa2565b91905055505f5f90505f5f90505f5f5f5b831580156110d15750600a85105b1561129e575f6001436110e49190613ae9565b4033600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054886040516020016111389493929190613ba1565b604051602081830303815290604052805190602001205f1c90505f816040516020016111649190613c38565b604051602081830303815290604052805190602001205f1c90505f826040516020016111909190613ca7565b604051602081830303815290604052805190602001205f1c90505f836040516020016111bc9190613d16565b604051602081830303815290604052805190602001205f1c9050608f836111e39190613d3b565b96506056826111f29190613d3b565b9550600d816112019190613d3b565b94505f87878760405160200161121993929190613d6b565b604051602081830303815290604052805190602001209050600c5f8281526020019081526020015f205f9054906101000a900460ff16611285576001600c5f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555060019850611294565b898061129090613aa2565b9a50505b50505050506110c3565b836112de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d590613e17565b60405180910390fd5b600a5f8154809291906112f090613aa2565b91905055505f600a549050604051806060016040528085815260200184815260200183815250600b5f8381526020019081526020015f205f820151815f015560208201518160010155604082015181600201559050506113508882612516565b809650505050505050919050565b600b602052805f5260405f205f91509050805f0154908060010154908060020154905083565b61138c611980565b5f4790505f81116113d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113c990613f14565b60405180910390fd5b6113da610a00565b73ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f1935050505015801561141c573d5f5f3e3d5ffd5b5050565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6114b6611980565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611526575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161151d9190612ec7565b60405180910390fd5b61152f81611a07565b50565b61153a611980565b5f8190505f8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016115789190612ec7565b602060405180830381865afa158015611593573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115b79190613f46565b90505f81116115fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115f290613fbb565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61161f610a00565b836040518363ffffffff1660e01b815260040161163d929190613072565b6020604051808303815f875af1158015611659573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061167d9190613fed565b50505050565b5f61168d82612609565b9050919050565b5f5f61169f836126ea565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361171157826040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016117089190612f57565b60405180910390fd5b80915050919050565b5f60065f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6117678383836001612723565b505050565b5f5f611777846126ea565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146117b8576117b78184866128e2565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611843576117f75f855f5f612723565b600160055f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146118c257600160055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460045f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b5f612710905090565b611988611753565b73ffffffffffffffffffffffffffffffffffffffff166119a6610a00565b73ffffffffffffffffffffffffffffffffffffffff1614611a05576119c9611753565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016119fc9190612ec7565b60405180910390fd5b565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611b3a57816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611b319190612ec7565b60405180910390fd5b8060075f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611c269190612d81565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115611dd8578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b8152600401611c91949392919061406a565b6020604051808303815f875af1925050508015611ccc57506040513d601f19601f82011682018060405250810190611cc991906140c8565b60015b611d4d573d805f8114611cfa576040519150601f19603f3d011682016040523d82523d5f602084013e611cff565b606091505b505f815103611d4557836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611d3c9190612ec7565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611dd657836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611dcd9190612ec7565b60405180910390fd5b505b5050505050565b60605f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384855f886040518363ffffffff1660e01b8152600401611e3e929190614138565b5f60405180830381865afa158015611e58573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611e8091906141fd565b90505f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856005866040518363ffffffff1660e01b8152600401611ee092919061427d565b5f60405180830381865afa158015611efa573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611f2291906141fd565b90505f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856003896040518363ffffffff1660e01b8152600401611f829291906142dd565b5f60405180830381865afa158015611f9c573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611fc491906141fd565b90505f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856004896040518363ffffffff1660e01b815260040161202492919061433d565b5f60405180830381865afa15801561203e573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061206691906141fd565b90508383838360405160200161207f9493929190614444565b604051602081830303815290604052945050505050949350505050565b60605f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b85f886040518363ffffffff1660e01b81526004016120fb929190614138565b5f60405180830381865afa158015612115573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061213d91906141fd565b90508060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86003886040518363ffffffff1660e01b815260040161219d9291906142dd565b5f60405180830381865afa1580156121b7573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906121df91906141fd565b6040516020016121f09291906144e1565b60405160208183030381529060405290508060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86004876040518363ffffffff1660e01b815260040161225f92919061433d565b5f60405180830381865afa158015612279573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906122a191906141fd565b6040516020016122b29291906144e1565b60405160208183030381529060405290508060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86005866040518363ffffffff1660e01b815260040161232192919061427d565b5f60405180830381865afa15801561233b573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061236391906141fd565b6040516020016123749291906144e1565b604051602081830303815290604052905080915050949350505050565b60605f82036123d7576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506124e4565b5f8290505f5b5f82146124065780806123ef90613aa2565b915050600a826123ff91906135ad565b91506123dd565b5f8167ffffffffffffffff81111561242157612420613192565b5b6040519080825280601f01601f1916602001820160405280156124535781602001600182028036833780820191505090505b5090505b5f85146124dd5781806124699061450f565b925050600a856124799190613d3b565b603061248591906139e1565b60f81b81838151811061249b5761249a613e35565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a856124d691906135ad565b9450612457565b8093505050505b919050565b606061250f826040518060600160405280604081526020016145376040913960016129a5565b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612586575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161257d9190612ec7565b60405180910390fd5b5f61259283835f61176c565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612604575f6040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081526004016125fb9190612ec7565b60405180910390fd5b505050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806126d357507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806126e357506126e282612b34565b5b9050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061275b57505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b1561288d575f61276a84611694565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156127d457508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156127e757506127e58184611420565b155b1561282957826040517fa9fbf51f0000000000000000000000000000000000000000000000000000000081526004016128209190612ec7565b60405180910390fd5b811561288b57838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360065f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b6128ed838383612bad565b6129a0575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361296157806040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016129589190612f57565b60405180910390fd5b81816040517f177e802f000000000000000000000000000000000000000000000000000000008152600401612997929190613072565b60405180910390fd5b505050565b60605f8451036129c55760405180602001604052805f8152509050612b2d565b5f826129f65760036002865160046129dd919061353f565b6129e791906139e1565b6129f191906135ad565b612a1d565b600360028651612a0691906139e1565b612a1091906135ad565b6004612a1c919061353f565b5b90505f8167ffffffffffffffff811115612a3a57612a39613192565b5b6040519080825280601f01601f191660200182016040528015612a6c5781602001600182028036833780820191505090505b509050600185016020820187885189016020810180515f82525b82841015612ae1576003840193508351603f8160121c168701518653600186019550603f81600c1c168701518653600186019550603f8160061c168701518653600186019550603f8116870151865360018601955050612a86565b8082528915612b215760038c510660018114612b045760028114612b1757612b1f565b603d6001870353603d6002870353612b1f565b603d60018703535b505b50505050505080925050505b9392505050565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612ba65750612ba582612c6d565b5b9050919050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612c6457508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612c255750612c248484611420565b5b80612c6357508273ffffffffffffffffffffffffffffffffffffffff16612c4b8361171a565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612d1b81612ce7565b8114612d25575f5ffd5b50565b5f81359050612d3681612d12565b92915050565b5f60208284031215612d5157612d50612cdf565b5b5f612d5e84828501612d28565b91505092915050565b5f8115159050919050565b612d7b81612d67565b82525050565b5f602082019050612d945f830184612d72565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612ddc82612d9a565b612de68185612da4565b9350612df6818560208601612db4565b612dff81612dc2565b840191505092915050565b5f6020820190508181035f830152612e228184612dd2565b905092915050565b5f819050919050565b612e3c81612e2a565b8114612e46575f5ffd5b50565b5f81359050612e5781612e33565b92915050565b5f60208284031215612e7257612e71612cdf565b5b5f612e7f84828501612e49565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612eb182612e88565b9050919050565b612ec181612ea7565b82525050565b5f602082019050612eda5f830184612eb8565b92915050565b612ee981612ea7565b8114612ef3575f5ffd5b50565b5f81359050612f0481612ee0565b92915050565b5f5f60408385031215612f2057612f1f612cdf565b5b5f612f2d85828601612ef6565b9250506020612f3e85828601612e49565b9150509250929050565b612f5181612e2a565b82525050565b5f602082019050612f6a5f830184612f48565b92915050565b5f819050919050565b5f612f93612f8e612f8984612e88565b612f70565b612e88565b9050919050565b5f612fa482612f79565b9050919050565b5f612fb582612f9a565b9050919050565b612fc581612fab565b82525050565b5f602082019050612fde5f830184612fbc565b92915050565b5f5f5f60608486031215612ffb57612ffa612cdf565b5b5f61300886828701612ef6565b935050602061301986828701612ef6565b925050604061302a86828701612e49565b9150509250925092565b5f5f6040838503121561304a57613049612cdf565b5b5f61305785828601612e49565b925050602061306885828601612e49565b9150509250929050565b5f6040820190506130855f830185612eb8565b6130926020830184612f48565b9392505050565b5f819050919050565b6130ab81613099565b81146130b5575f5ffd5b50565b5f813590506130c6816130a2565b92915050565b5f602082840312156130e1576130e0612cdf565b5b5f6130ee848285016130b8565b91505092915050565b5f6020828403121561310c5761310b612cdf565b5b5f61311984828501612ef6565b91505092915050565b61312b81612d67565b8114613135575f5ffd5b50565b5f8135905061314681613122565b92915050565b5f5f6040838503121561316257613161612cdf565b5b5f61316f85828601612ef6565b925050602061318085828601613138565b9150509250929050565b5f5ffd5b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6131c882612dc2565b810181811067ffffffffffffffff821117156131e7576131e6613192565b5b80604052505050565b5f6131f9612cd6565b905061320582826131bf565b919050565b5f67ffffffffffffffff82111561322457613223613192565b5b61322d82612dc2565b9050602081019050919050565b828183375f83830152505050565b5f61325a6132558461320a565b6131f0565b9050828152602081018484840111156132765761327561318e565b5b61328184828561323a565b509392505050565b5f82601f83011261329d5761329c61318a565b5b81356132ad848260208601613248565b91505092915050565b5f5f5f5f608085870312156132ce576132cd612cdf565b5b5f6132db87828801612ef6565b94505060206132ec87828801612ef6565b93505060406132fd87828801612e49565b925050606085013567ffffffffffffffff81111561331e5761331d612ce3565b5b61332a87828801613289565b91505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61336881612e2a565b82525050565b5f613379838361335f565b60208301905092915050565b5f602082019050919050565b5f61339b82613336565b6133a58185613340565b93506133b083613350565b805f5b838110156133e05781516133c7888261336e565b97506133d283613385565b9250506001810190506133b3565b5085935050505092915050565b5f6020820190508181035f8301526134058184613391565b905092915050565b5f6060820190506134205f830186612f48565b61342d6020830185612f48565b61343a6040830184612f48565b949350505050565b5f5f6040838503121561345857613457612cdf565b5b5f61346585828601612ef6565b925050602061347685828601612ef6565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806134c457607f821691505b6020821081036134d7576134d6613480565b5b50919050565b5f6060820190506134f05f830186612eb8565b6134fd6020830185612f48565b61350a6040830184612eb8565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61354982612e2a565b915061355483612e2a565b925082820261356281612e2a565b9150828204841483151761357957613578613512565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6135b782612e2a565b91506135c283612e2a565b9250826135d2576135d1613580565b5b828204905092915050565b5f81905092915050565b7f7b226e616d65223a225370696b792023000000000000000000000000000000005f82015250565b5f61361b6010836135dd565b9150613626826135e7565b601082019050919050565b5f61363b82612d9a565b61364581856135dd565b9350613655818560208601612db4565b80840191505092915050565b7f222c0000000000000000000000000000000000000000000000000000000000005f82015250565b5f6136956002836135dd565b91506136a082613661565b600282019050919050565b7f226465736372697074696f6e223a22416e206f6e2d636861696e20696d706c655f8201527f6d656e746174696f6e206f66205370696b696573204e4654206f6e204170654360208201527f6861696e2e204f435370696b69657320617265204461726b206d6f6465204f6e60408201527f2d436861696e2076617269616e7473206f66205370696b696573204e4654222c606082015250565b5f6137516080836135dd565b915061375c826136ab565b608082019050919050565b7f22696d616765223a22646174613a696d6167652f7376672b786d6c3b626173655f8201527f36342c0000000000000000000000000000000000000000000000000000000000602082015250565b5f6137c16023836135dd565b91506137cc82613767565b602382019050919050565b7f2261747472696275746573223a5b0000000000000000000000000000000000005f82015250565b5f61380b600e836135dd565b9150613816826137d7565b600e82019050919050565b7f5d7d0000000000000000000000000000000000000000000000000000000000005f82015250565b5f6138556002836135dd565b915061386082613821565b600282019050919050565b5f6138758261360f565b91506138818286613631565b915061388c82613689565b915061389782613745565b91506138a2826137b5565b91506138ae8285613631565b91506138b982613689565b91506138c4826137ff565b91506138d08284613631565b91506138db82613849565b9150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f61391c601d836135dd565b9150613927826138e8565b601d82019050919050565b5f61393c82613910565b91506139488284613631565b915081905092915050565b7f5175616e74697479206d757374206265206265747765656e203120616e6420355f8201527f3035000000000000000000000000000000000000000000000000000000000000602082015250565b5f6139ad602283612da4565b91506139b882613953565b604082019050919050565b5f6020820190508181035f8301526139da816139a1565b9050919050565b5f6139eb82612e2a565b91506139f683612e2a565b9250828201905080821115613a0e57613a0d613512565b5b92915050565b7f4261746368206d696e7420776f756c6420657863656564206d617820737570705f8201527f6c79000000000000000000000000000000000000000000000000000000000000602082015250565b5f613a6e602283612da4565b9150613a7982613a14565b604082019050919050565b5f6020820190508181035f830152613a9b81613a62565b9050919050565b5f613aac82612e2a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ade57613add613512565b5b600182019050919050565b5f613af382612e2a565b9150613afe83612e2a565b9250828203905081811115613b1657613b15613512565b5b92915050565b5f819050919050565b613b36613b3182613099565b613b1c565b82525050565b5f8160601b9050919050565b5f613b5282613b3c565b9050919050565b5f613b6382613b48565b9050919050565b613b7b613b7682612ea7565b613b59565b82525050565b5f819050919050565b613b9b613b9682612e2a565b613b81565b82525050565b5f613bac8287613b25565b602082019150613bbc8286613b6a565b601482019150613bcc8285613b8a565b602082019150613bdc8284613b8a565b60208201915081905095945050505050565b7f65796573000000000000000000000000000000000000000000000000000000005f82015250565b5f613c226004836135dd565b9150613c2d82613bee565b600482019050919050565b5f613c438284613b8a565b602082019150613c5282613c16565b915081905092915050565b7f68656164730000000000000000000000000000000000000000000000000000005f82015250565b5f613c916005836135dd565b9150613c9c82613c5d565b600582019050919050565b5f613cb28284613b8a565b602082019150613cc182613c85565b915081905092915050565b7f6d6f7574687300000000000000000000000000000000000000000000000000005f82015250565b5f613d006006836135dd565b9150613d0b82613ccc565b600682019050919050565b5f613d218284613b8a565b602082019150613d3082613cf4565b915081905092915050565b5f613d4582612e2a565b9150613d5083612e2a565b925082613d6057613d5f613580565b5b828206905092915050565b5f613d768286613b8a565b602082019150613d868285613b8a565b602082019150613d968284613b8a565b602082019150819050949350505050565b7f4e6f20756e6971756520636f6d62696e6174696f6e20666f756e6420616674655f8201527f7220313020617474656d70747300000000000000000000000000000000000000602082015250565b5f613e01602d83612da4565b9150613e0c82613da7565b604082019050919050565b5f6020820190508181035f830152613e2e81613df5565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f613e96601283612da4565b9150613ea182613e62565b602082019050919050565b5f6020820190508181035f830152613ec381613e8a565b9050919050565b7f4e6f2045544820746f20776974686472617700000000000000000000000000005f82015250565b5f613efe601283612da4565b9150613f0982613eca565b602082019050919050565b5f6020820190508181035f830152613f2b81613ef2565b9050919050565b5f81519050613f4081612e33565b92915050565b5f60208284031215613f5b57613f5a612cdf565b5b5f613f6884828501613f32565b91505092915050565b7f4e6f20746f6b656e7320746f20776974686472617700000000000000000000005f82015250565b5f613fa5601583612da4565b9150613fb082613f71565b602082019050919050565b5f6020820190508181035f830152613fd281613f99565b9050919050565b5f81519050613fe781613122565b92915050565b5f6020828403121561400257614001612cdf565b5b5f61400f84828501613fd9565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f61403c82614018565b6140468185614022565b9350614056818560208601612db4565b61405f81612dc2565b840191505092915050565b5f60808201905061407d5f830187612eb8565b61408a6020830186612eb8565b6140976040830185612f48565b81810360608301526140a98184614032565b905095945050505050565b5f815190506140c281612d12565b92915050565b5f602082840312156140dd576140dc612cdf565b5b5f6140ea848285016140b4565b91505092915050565b5f819050919050565b5f60ff82169050919050565b5f61412261411d614118846140f3565b612f70565b6140fc565b9050919050565b61413281614108565b82525050565b5f60408201905061414b5f830185614129565b6141586020830184612f48565b9392505050565b5f67ffffffffffffffff82111561417957614178613192565b5b61418282612dc2565b9050602081019050919050565b5f6141a161419c8461415f565b6131f0565b9050828152602081018484840111156141bd576141bc61318e565b5b6141c8848285612db4565b509392505050565b5f82601f8301126141e4576141e361318a565b5b81516141f484826020860161418f565b91505092915050565b5f6020828403121561421257614211612cdf565b5b5f82015167ffffffffffffffff81111561422f5761422e612ce3565b5b61423b848285016141d0565b91505092915050565b5f819050919050565b5f61426761426261425d84614244565b612f70565b6140fc565b9050919050565b6142778161424d565b82525050565b5f6040820190506142905f83018561426e565b61429d6020830184612f48565b9392505050565b5f819050919050565b5f6142c76142c26142bd846142a4565b612f70565b6140fc565b9050919050565b6142d7816142ad565b82525050565b5f6040820190506142f05f8301856142ce565b6142fd6020830184612f48565b9392505050565b5f819050919050565b5f61432761432261431d84614304565b612f70565b6140fc565b9050919050565b6143378161430d565b82525050565b5f6040820190506143505f83018561432e565b61435d6020830184612f48565b9392505050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f32305f8201527f30302f737667222077696474683d2235313222206865696768743d223531322260208201527f2076696577426f783d223020302035313220353132223e000000000000000000604082015250565b5f6143e46057836135dd565b91506143ef82614364565b605782019050919050565b7f3c2f7376673e00000000000000000000000000000000000000000000000000005f82015250565b5f61442e6006836135dd565b9150614439826143fa565b600682019050919050565b5f61444e826143d8565b915061445a8287613631565b91506144668286613631565b91506144728285613631565b915061447e8284613631565b915061448982614422565b915081905095945050505050565b7f2c000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6144cb6001836135dd565b91506144d682614497565b600182019050919050565b5f6144ec8285613631565b91506144f7826144bf565b91506145038284613631565b91508190509392505050565b5f61451982612e2a565b91505f820361452b5761452a613512565b5b60018203905091905056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212202c0963c22cdf73981de98a45690851d2f22013786ccd482191c8f1d1cde8aac664736f6c634300081c0033000000000000000000000000a77a68e1e3820b36066496084a8b872c27b312a7000000000000000000000000a3097f1df53cc1d55e0ba7f2299811fe4940e24d
Deployed Bytecode
0x608060405234801561000f575f5ffd5b50600436106101c2575f3560e01c80637ecebe00116100f7578063d023f37e11610095578063e086e5ec1161006f578063e086e5ec14610541578063e985e9c51461054b578063f2fde38b1461057b578063f4f3b20014610597576101c2565b8063d023f37e146104af578063d1cea4ec146104df578063e05c57bf1461050f576101c2565b8063a22cb465116100d1578063a22cb46514610429578063b88d4fde14610445578063c87b56dd14610461578063cfdbf25414610491576101c2565b80637ecebe00146103bd5780638da5cb5b146103ed57806395d89b411461040b576101c2565b80632a55205a1161016457806349bc4aed1161013e57806349bc4aed146103235780636352211e1461035357806370a0823114610383578063715018a6146103b3576101c2565b80632a55205a146102b857806332cb6b0c146102e957806342842e0e14610307576101c2565b8063095ea7b3116101a0578063095ea7b31461024457806318160ddd146102605780631b076edc1461027e57806323b872dd1461029c576101c2565b806301ffc9a7146101c657806306fdde03146101f6578063081812fc14610214575b5f5ffd5b6101e060048036038101906101db9190612d3c565b6105b3565b6040516101ed9190612d81565b60405180910390f35b6101fe6105c4565b60405161020b9190612e0a565b60405180910390f35b61022e60048036038101906102299190612e5d565b610654565b60405161023b9190612ec7565b60405180910390f35b61025e60048036038101906102599190612f0a565b61066f565b005b610268610685565b6040516102759190612f57565b60405180910390f35b61028661068b565b6040516102939190612fcb565b60405180910390f35b6102b660048036038101906102b19190612fe4565b6106b0565b005b6102d260048036038101906102cd9190613034565b6107af565b6040516102e0929190613072565b60405180910390f35b6102f16108cf565b6040516102fe9190612f57565b60405180910390f35b610321600480360381019061031c9190612fe4565b6108d5565b005b61033d600480360381019061033891906130cc565b6108f4565b60405161034a9190612d81565b60405180910390f35b61036d60048036038101906103689190612e5d565b610911565b60405161037a9190612ec7565b60405180910390f35b61039d600480360381019061039891906130f7565b610922565b6040516103aa9190612f57565b60405180910390f35b6103bb6109d8565b005b6103d760048036038101906103d291906130f7565b6109eb565b6040516103e49190612f57565b60405180910390f35b6103f5610a00565b6040516104029190612ec7565b60405180910390f35b610413610a28565b6040516104209190612e0a565b60405180910390f35b610443600480360381019061043e919061314c565b610ab8565b005b61045f600480360381019061045a91906132b6565b610ace565b005b61047b60048036038101906104769190612e5d565b610af3565b6040516104889190612e0a565b60405180910390f35b610499610be2565b6040516104a69190612f57565b60405180910390f35b6104c960048036038101906104c49190612f0a565b610be8565b6040516104d691906133ed565b60405180910390f35b6104f960048036038101906104f491906130f7565b611016565b6040516105069190612f57565b60405180910390f35b61052960048036038101906105249190612e5d565b61135e565b6040516105389392919061340d565b60405180910390f35b610549611384565b005b61056560048036038101906105609190613442565b611420565b6040516105729190612d81565b60405180910390f35b610595600480360381019061059091906130f7565b6114ae565b005b6105b160048036038101906105ac91906130f7565b611532565b005b5f6105bd82611683565b9050919050565b6060600280546105d3906134ad565b80601f01602080910402602001604051908101604052809291908181526020018280546105ff906134ad565b801561064a5780601f106106215761010080835404028352916020019161064a565b820191905f5260205f20905b81548152906001019060200180831161062d57829003601f168201915b5050505050905090565b5f61065e82611694565b506106688261171a565b9050919050565b610681828261067c611753565b61175a565b5050565b600a5481565b60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610720575f6040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016107179190612ec7565b60405180910390fd5b5f610733838361072e611753565b61176c565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146107a9578382826040517f64283d7b0000000000000000000000000000000000000000000000000000000081526004016107a0939291906134dd565b60405180910390fd5b50505050565b5f5f5f60015f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610881575f5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505f5f0160149054906101000a90046bffffffffffffffffffffffff1690505b5f61088a611977565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff16886108b2919061353f565b6108bc91906135ad565b9050828195509550505050509250929050565b6115b381565b6108ef83838360405180602001604052805f815250610ace565b505050565b600c602052805f5260405f205f915054906101000a900460ff1681565b5f61091b82611694565b9050919050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610993575f6040517f89c62b6400000000000000000000000000000000000000000000000000000000815260040161098a9190612ec7565b60405180910390fd5b60055f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6109e0611980565b6109e95f611a07565b565b600d602052805f5260405f205f915090505481565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060038054610a37906134ad565b80601f0160208091040260200160405190810160405280929190818152602001828054610a63906134ad565b8015610aae5780601f10610a8557610100808354040283529160200191610aae565b820191905f5260205f20905b815481529060010190602001808311610a9157829003601f168201915b5050505050905090565b610aca610ac3611753565b8383611aca565b5050565b610ad98484846106b0565b610aed610ae4611753565b85858585611c33565b50505050565b6060610afe82610911565b505f600b5f8481526020019081526020015f206040518060600160405290815f82015481526020016001820154815260200160028201548152505090505f5f90505f825f015190505f836020015190505f846040015190505f610b6385858585611ddf565b90505f610b728686868661209c565b90505f610b7e8a612391565b610b87846124e9565b83604051602001610b9a9392919061386b565b6040516020818303038152906040529050610bb4816124e9565b604051602001610bc49190613932565b60405160208183030381529060405298505050505050505050919050565b6101f981565b6060610bf2611980565b5f82118015610c0357506101f98211155b610c42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c39906139c3565b60405180910390fd5b6115b382600a54610c5391906139e1565b1115610c94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8b90613a84565b60405180910390fd5b5f8267ffffffffffffffff811115610caf57610cae613192565b5b604051908082528060200260200182016040528015610cdd5781602001602082028036833780820191505090505b5090505f5f90505b8381101561100b57600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610d3a90613aa2565b91905055505f5f90505f5f90505f5f5f5b83158015610d595750600a85105b15610f26575f600143610d6c9190613ae9565b4033600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205488604051602001610dc09493929190613ba1565b604051602081830303815290604052805190602001205f1c90505f81604051602001610dec9190613c38565b604051602081830303815290604052805190602001205f1c90505f82604051602001610e189190613ca7565b604051602081830303815290604052805190602001205f1c90505f83604051602001610e449190613d16565b604051602081830303815290604052805190602001205f1c9050608f83610e6b9190613d3b565b9650605682610e7a9190613d3b565b9550600d81610e899190613d3b565b94505f878787604051602001610ea193929190613d6b565b604051602081830303815290604052805190602001209050600c5f8281526020019081526020015f205f9054906101000a900460ff16610f0d576001600c5f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555060019850610f1c565b8980610f1890613aa2565b9a50505b5050505050610d4b565b83610f66576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5d90613e17565b60405180910390fd5b600a5f815480929190610f7890613aa2565b91905055505f600a549050604051806060016040528085815260200184815260200183815250600b5f8381526020019081526020015f205f820151815f01556020820151816001015560408201518160020155905050610fd88b82612516565b80888881518110610fec57610feb613e35565b5b6020026020010181815250505050505050508080600101915050610ce5565b508091505092915050565b5f61101f611980565b6115b3600a5410611065576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105c90613eac565b60405180910390fd5b600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154809291906110b290613aa2565b91905055505f5f90505f5f90505f5f5f5b831580156110d15750600a85105b1561129e575f6001436110e49190613ae9565b4033600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054886040516020016111389493929190613ba1565b604051602081830303815290604052805190602001205f1c90505f816040516020016111649190613c38565b604051602081830303815290604052805190602001205f1c90505f826040516020016111909190613ca7565b604051602081830303815290604052805190602001205f1c90505f836040516020016111bc9190613d16565b604051602081830303815290604052805190602001205f1c9050608f836111e39190613d3b565b96506056826111f29190613d3b565b9550600d816112019190613d3b565b94505f87878760405160200161121993929190613d6b565b604051602081830303815290604052805190602001209050600c5f8281526020019081526020015f205f9054906101000a900460ff16611285576001600c5f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555060019850611294565b898061129090613aa2565b9a50505b50505050506110c3565b836112de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d590613e17565b60405180910390fd5b600a5f8154809291906112f090613aa2565b91905055505f600a549050604051806060016040528085815260200184815260200183815250600b5f8381526020019081526020015f205f820151815f015560208201518160010155604082015181600201559050506113508882612516565b809650505050505050919050565b600b602052805f5260405f205f91509050805f0154908060010154908060020154905083565b61138c611980565b5f4790505f81116113d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113c990613f14565b60405180910390fd5b6113da610a00565b73ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f1935050505015801561141c573d5f5f3e3d5ffd5b5050565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6114b6611980565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611526575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161151d9190612ec7565b60405180910390fd5b61152f81611a07565b50565b61153a611980565b5f8190505f8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016115789190612ec7565b602060405180830381865afa158015611593573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115b79190613f46565b90505f81116115fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115f290613fbb565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61161f610a00565b836040518363ffffffff1660e01b815260040161163d929190613072565b6020604051808303815f875af1158015611659573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061167d9190613fed565b50505050565b5f61168d82612609565b9050919050565b5f5f61169f836126ea565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361171157826040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016117089190612f57565b60405180910390fd5b80915050919050565b5f60065f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6117678383836001612723565b505050565b5f5f611777846126ea565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146117b8576117b78184866128e2565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611843576117f75f855f5f612723565b600160055f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146118c257600160055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460045f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b5f612710905090565b611988611753565b73ffffffffffffffffffffffffffffffffffffffff166119a6610a00565b73ffffffffffffffffffffffffffffffffffffffff1614611a05576119c9611753565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016119fc9190612ec7565b60405180910390fd5b565b5f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611b3a57816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611b319190612ec7565b60405180910390fd5b8060075f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611c269190612d81565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115611dd8578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b8152600401611c91949392919061406a565b6020604051808303815f875af1925050508015611ccc57506040513d601f19601f82011682018060405250810190611cc991906140c8565b60015b611d4d573d805f8114611cfa576040519150601f19603f3d011682016040523d82523d5f602084013e611cff565b606091505b505f815103611d4557836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611d3c9190612ec7565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611dd657836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611dcd9190612ec7565b60405180910390fd5b505b5050505050565b60605f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384855f886040518363ffffffff1660e01b8152600401611e3e929190614138565b5f60405180830381865afa158015611e58573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611e8091906141fd565b90505f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856005866040518363ffffffff1660e01b8152600401611ee092919061427d565b5f60405180830381865afa158015611efa573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611f2291906141fd565b90505f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856003896040518363ffffffff1660e01b8152600401611f829291906142dd565b5f60405180830381865afa158015611f9c573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611fc491906141fd565b90505f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856004896040518363ffffffff1660e01b815260040161202492919061433d565b5f60405180830381865afa15801561203e573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061206691906141fd565b90508383838360405160200161207f9493929190614444565b604051602081830303815290604052945050505050949350505050565b60605f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b85f886040518363ffffffff1660e01b81526004016120fb929190614138565b5f60405180830381865afa158015612115573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061213d91906141fd565b90508060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86003886040518363ffffffff1660e01b815260040161219d9291906142dd565b5f60405180830381865afa1580156121b7573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906121df91906141fd565b6040516020016121f09291906144e1565b60405160208183030381529060405290508060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86004876040518363ffffffff1660e01b815260040161225f92919061433d565b5f60405180830381865afa158015612279573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906122a191906141fd565b6040516020016122b29291906144e1565b60405160208183030381529060405290508060095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86005866040518363ffffffff1660e01b815260040161232192919061427d565b5f60405180830381865afa15801561233b573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061236391906141fd565b6040516020016123749291906144e1565b604051602081830303815290604052905080915050949350505050565b60605f82036123d7576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506124e4565b5f8290505f5b5f82146124065780806123ef90613aa2565b915050600a826123ff91906135ad565b91506123dd565b5f8167ffffffffffffffff81111561242157612420613192565b5b6040519080825280601f01601f1916602001820160405280156124535781602001600182028036833780820191505090505b5090505b5f85146124dd5781806124699061450f565b925050600a856124799190613d3b565b603061248591906139e1565b60f81b81838151811061249b5761249a613e35565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a856124d691906135ad565b9450612457565b8093505050505b919050565b606061250f826040518060600160405280604081526020016145376040913960016129a5565b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612586575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161257d9190612ec7565b60405180910390fd5b5f61259283835f61176c565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612604575f6040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081526004016125fb9190612ec7565b60405180910390fd5b505050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806126d357507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806126e357506126e282612b34565b5b9050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061275b57505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b1561288d575f61276a84611694565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156127d457508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156127e757506127e58184611420565b155b1561282957826040517fa9fbf51f0000000000000000000000000000000000000000000000000000000081526004016128209190612ec7565b60405180910390fd5b811561288b57838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360065f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b6128ed838383612bad565b6129a0575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361296157806040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016129589190612f57565b60405180910390fd5b81816040517f177e802f000000000000000000000000000000000000000000000000000000008152600401612997929190613072565b60405180910390fd5b505050565b60605f8451036129c55760405180602001604052805f8152509050612b2d565b5f826129f65760036002865160046129dd919061353f565b6129e791906139e1565b6129f191906135ad565b612a1d565b600360028651612a0691906139e1565b612a1091906135ad565b6004612a1c919061353f565b5b90505f8167ffffffffffffffff811115612a3a57612a39613192565b5b6040519080825280601f01601f191660200182016040528015612a6c5781602001600182028036833780820191505090505b509050600185016020820187885189016020810180515f82525b82841015612ae1576003840193508351603f8160121c168701518653600186019550603f81600c1c168701518653600186019550603f8160061c168701518653600186019550603f8116870151865360018601955050612a86565b8082528915612b215760038c510660018114612b045760028114612b1757612b1f565b603d6001870353603d6002870353612b1f565b603d60018703535b505b50505050505080925050505b9392505050565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612ba65750612ba582612c6d565b5b9050919050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612c6457508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612c255750612c248484611420565b5b80612c6357508273ffffffffffffffffffffffffffffffffffffffff16612c4b8361171a565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612d1b81612ce7565b8114612d25575f5ffd5b50565b5f81359050612d3681612d12565b92915050565b5f60208284031215612d5157612d50612cdf565b5b5f612d5e84828501612d28565b91505092915050565b5f8115159050919050565b612d7b81612d67565b82525050565b5f602082019050612d945f830184612d72565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612ddc82612d9a565b612de68185612da4565b9350612df6818560208601612db4565b612dff81612dc2565b840191505092915050565b5f6020820190508181035f830152612e228184612dd2565b905092915050565b5f819050919050565b612e3c81612e2a565b8114612e46575f5ffd5b50565b5f81359050612e5781612e33565b92915050565b5f60208284031215612e7257612e71612cdf565b5b5f612e7f84828501612e49565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612eb182612e88565b9050919050565b612ec181612ea7565b82525050565b5f602082019050612eda5f830184612eb8565b92915050565b612ee981612ea7565b8114612ef3575f5ffd5b50565b5f81359050612f0481612ee0565b92915050565b5f5f60408385031215612f2057612f1f612cdf565b5b5f612f2d85828601612ef6565b9250506020612f3e85828601612e49565b9150509250929050565b612f5181612e2a565b82525050565b5f602082019050612f6a5f830184612f48565b92915050565b5f819050919050565b5f612f93612f8e612f8984612e88565b612f70565b612e88565b9050919050565b5f612fa482612f79565b9050919050565b5f612fb582612f9a565b9050919050565b612fc581612fab565b82525050565b5f602082019050612fde5f830184612fbc565b92915050565b5f5f5f60608486031215612ffb57612ffa612cdf565b5b5f61300886828701612ef6565b935050602061301986828701612ef6565b925050604061302a86828701612e49565b9150509250925092565b5f5f6040838503121561304a57613049612cdf565b5b5f61305785828601612e49565b925050602061306885828601612e49565b9150509250929050565b5f6040820190506130855f830185612eb8565b6130926020830184612f48565b9392505050565b5f819050919050565b6130ab81613099565b81146130b5575f5ffd5b50565b5f813590506130c6816130a2565b92915050565b5f602082840312156130e1576130e0612cdf565b5b5f6130ee848285016130b8565b91505092915050565b5f6020828403121561310c5761310b612cdf565b5b5f61311984828501612ef6565b91505092915050565b61312b81612d67565b8114613135575f5ffd5b50565b5f8135905061314681613122565b92915050565b5f5f6040838503121561316257613161612cdf565b5b5f61316f85828601612ef6565b925050602061318085828601613138565b9150509250929050565b5f5ffd5b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6131c882612dc2565b810181811067ffffffffffffffff821117156131e7576131e6613192565b5b80604052505050565b5f6131f9612cd6565b905061320582826131bf565b919050565b5f67ffffffffffffffff82111561322457613223613192565b5b61322d82612dc2565b9050602081019050919050565b828183375f83830152505050565b5f61325a6132558461320a565b6131f0565b9050828152602081018484840111156132765761327561318e565b5b61328184828561323a565b509392505050565b5f82601f83011261329d5761329c61318a565b5b81356132ad848260208601613248565b91505092915050565b5f5f5f5f608085870312156132ce576132cd612cdf565b5b5f6132db87828801612ef6565b94505060206132ec87828801612ef6565b93505060406132fd87828801612e49565b925050606085013567ffffffffffffffff81111561331e5761331d612ce3565b5b61332a87828801613289565b91505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61336881612e2a565b82525050565b5f613379838361335f565b60208301905092915050565b5f602082019050919050565b5f61339b82613336565b6133a58185613340565b93506133b083613350565b805f5b838110156133e05781516133c7888261336e565b97506133d283613385565b9250506001810190506133b3565b5085935050505092915050565b5f6020820190508181035f8301526134058184613391565b905092915050565b5f6060820190506134205f830186612f48565b61342d6020830185612f48565b61343a6040830184612f48565b949350505050565b5f5f6040838503121561345857613457612cdf565b5b5f61346585828601612ef6565b925050602061347685828601612ef6565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806134c457607f821691505b6020821081036134d7576134d6613480565b5b50919050565b5f6060820190506134f05f830186612eb8565b6134fd6020830185612f48565b61350a6040830184612eb8565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61354982612e2a565b915061355483612e2a565b925082820261356281612e2a565b9150828204841483151761357957613578613512565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6135b782612e2a565b91506135c283612e2a565b9250826135d2576135d1613580565b5b828204905092915050565b5f81905092915050565b7f7b226e616d65223a225370696b792023000000000000000000000000000000005f82015250565b5f61361b6010836135dd565b9150613626826135e7565b601082019050919050565b5f61363b82612d9a565b61364581856135dd565b9350613655818560208601612db4565b80840191505092915050565b7f222c0000000000000000000000000000000000000000000000000000000000005f82015250565b5f6136956002836135dd565b91506136a082613661565b600282019050919050565b7f226465736372697074696f6e223a22416e206f6e2d636861696e20696d706c655f8201527f6d656e746174696f6e206f66205370696b696573204e4654206f6e204170654360208201527f6861696e2e204f435370696b69657320617265204461726b206d6f6465204f6e60408201527f2d436861696e2076617269616e7473206f66205370696b696573204e4654222c606082015250565b5f6137516080836135dd565b915061375c826136ab565b608082019050919050565b7f22696d616765223a22646174613a696d6167652f7376672b786d6c3b626173655f8201527f36342c0000000000000000000000000000000000000000000000000000000000602082015250565b5f6137c16023836135dd565b91506137cc82613767565b602382019050919050565b7f2261747472696275746573223a5b0000000000000000000000000000000000005f82015250565b5f61380b600e836135dd565b9150613816826137d7565b600e82019050919050565b7f5d7d0000000000000000000000000000000000000000000000000000000000005f82015250565b5f6138556002836135dd565b915061386082613821565b600282019050919050565b5f6138758261360f565b91506138818286613631565b915061388c82613689565b915061389782613745565b91506138a2826137b5565b91506138ae8285613631565b91506138b982613689565b91506138c4826137ff565b91506138d08284613631565b91506138db82613849565b9150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f61391c601d836135dd565b9150613927826138e8565b601d82019050919050565b5f61393c82613910565b91506139488284613631565b915081905092915050565b7f5175616e74697479206d757374206265206265747765656e203120616e6420355f8201527f3035000000000000000000000000000000000000000000000000000000000000602082015250565b5f6139ad602283612da4565b91506139b882613953565b604082019050919050565b5f6020820190508181035f8301526139da816139a1565b9050919050565b5f6139eb82612e2a565b91506139f683612e2a565b9250828201905080821115613a0e57613a0d613512565b5b92915050565b7f4261746368206d696e7420776f756c6420657863656564206d617820737570705f8201527f6c79000000000000000000000000000000000000000000000000000000000000602082015250565b5f613a6e602283612da4565b9150613a7982613a14565b604082019050919050565b5f6020820190508181035f830152613a9b81613a62565b9050919050565b5f613aac82612e2a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ade57613add613512565b5b600182019050919050565b5f613af382612e2a565b9150613afe83612e2a565b9250828203905081811115613b1657613b15613512565b5b92915050565b5f819050919050565b613b36613b3182613099565b613b1c565b82525050565b5f8160601b9050919050565b5f613b5282613b3c565b9050919050565b5f613b6382613b48565b9050919050565b613b7b613b7682612ea7565b613b59565b82525050565b5f819050919050565b613b9b613b9682612e2a565b613b81565b82525050565b5f613bac8287613b25565b602082019150613bbc8286613b6a565b601482019150613bcc8285613b8a565b602082019150613bdc8284613b8a565b60208201915081905095945050505050565b7f65796573000000000000000000000000000000000000000000000000000000005f82015250565b5f613c226004836135dd565b9150613c2d82613bee565b600482019050919050565b5f613c438284613b8a565b602082019150613c5282613c16565b915081905092915050565b7f68656164730000000000000000000000000000000000000000000000000000005f82015250565b5f613c916005836135dd565b9150613c9c82613c5d565b600582019050919050565b5f613cb28284613b8a565b602082019150613cc182613c85565b915081905092915050565b7f6d6f7574687300000000000000000000000000000000000000000000000000005f82015250565b5f613d006006836135dd565b9150613d0b82613ccc565b600682019050919050565b5f613d218284613b8a565b602082019150613d3082613cf4565b915081905092915050565b5f613d4582612e2a565b9150613d5083612e2a565b925082613d6057613d5f613580565b5b828206905092915050565b5f613d768286613b8a565b602082019150613d868285613b8a565b602082019150613d968284613b8a565b602082019150819050949350505050565b7f4e6f20756e6971756520636f6d62696e6174696f6e20666f756e6420616674655f8201527f7220313020617474656d70747300000000000000000000000000000000000000602082015250565b5f613e01602d83612da4565b9150613e0c82613da7565b604082019050919050565b5f6020820190508181035f830152613e2e81613df5565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f613e96601283612da4565b9150613ea182613e62565b602082019050919050565b5f6020820190508181035f830152613ec381613e8a565b9050919050565b7f4e6f2045544820746f20776974686472617700000000000000000000000000005f82015250565b5f613efe601283612da4565b9150613f0982613eca565b602082019050919050565b5f6020820190508181035f830152613f2b81613ef2565b9050919050565b5f81519050613f4081612e33565b92915050565b5f60208284031215613f5b57613f5a612cdf565b5b5f613f6884828501613f32565b91505092915050565b7f4e6f20746f6b656e7320746f20776974686472617700000000000000000000005f82015250565b5f613fa5601583612da4565b9150613fb082613f71565b602082019050919050565b5f6020820190508181035f830152613fd281613f99565b9050919050565b5f81519050613fe781613122565b92915050565b5f6020828403121561400257614001612cdf565b5b5f61400f84828501613fd9565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f61403c82614018565b6140468185614022565b9350614056818560208601612db4565b61405f81612dc2565b840191505092915050565b5f60808201905061407d5f830187612eb8565b61408a6020830186612eb8565b6140976040830185612f48565b81810360608301526140a98184614032565b905095945050505050565b5f815190506140c281612d12565b92915050565b5f602082840312156140dd576140dc612cdf565b5b5f6140ea848285016140b4565b91505092915050565b5f819050919050565b5f60ff82169050919050565b5f61412261411d614118846140f3565b612f70565b6140fc565b9050919050565b61413281614108565b82525050565b5f60408201905061414b5f830185614129565b6141586020830184612f48565b9392505050565b5f67ffffffffffffffff82111561417957614178613192565b5b61418282612dc2565b9050602081019050919050565b5f6141a161419c8461415f565b6131f0565b9050828152602081018484840111156141bd576141bc61318e565b5b6141c8848285612db4565b509392505050565b5f82601f8301126141e4576141e361318a565b5b81516141f484826020860161418f565b91505092915050565b5f6020828403121561421257614211612cdf565b5b5f82015167ffffffffffffffff81111561422f5761422e612ce3565b5b61423b848285016141d0565b91505092915050565b5f819050919050565b5f61426761426261425d84614244565b612f70565b6140fc565b9050919050565b6142778161424d565b82525050565b5f6040820190506142905f83018561426e565b61429d6020830184612f48565b9392505050565b5f819050919050565b5f6142c76142c26142bd846142a4565b612f70565b6140fc565b9050919050565b6142d7816142ad565b82525050565b5f6040820190506142f05f8301856142ce565b6142fd6020830184612f48565b9392505050565b5f819050919050565b5f61432761432261431d84614304565b612f70565b6140fc565b9050919050565b6143378161430d565b82525050565b5f6040820190506143505f83018561432e565b61435d6020830184612f48565b9392505050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f32305f8201527f30302f737667222077696474683d2235313222206865696768743d223531322260208201527f2076696577426f783d223020302035313220353132223e000000000000000000604082015250565b5f6143e46057836135dd565b91506143ef82614364565b605782019050919050565b7f3c2f7376673e00000000000000000000000000000000000000000000000000005f82015250565b5f61442e6006836135dd565b9150614439826143fa565b600682019050919050565b5f61444e826143d8565b915061445a8287613631565b91506144668286613631565b91506144728285613631565b915061447e8284613631565b915061448982614422565b915081905095945050505050565b7f2c000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6144cb6001836135dd565b91506144d682614497565b600182019050919050565b5f6144ec8285613631565b91506144f7826144bf565b91506145038284613631565b91508190509392505050565b5f61451982612e2a565b91505f820361452b5761452a613512565b5b60018203905091905056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212202c0963c22cdf73981de98a45690851d2f22013786ccd482191c8f1d1cde8aac664736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a77a68e1e3820b36066496084a8b872c27b312a7000000000000000000000000a3097f1df53cc1d55e0ba7f2299811fe4940e24d
-----Decoded View---------------
Arg [0] : _dataSource (address): 0xA77A68E1E3820B36066496084A8b872c27B312A7
Arg [1] : royaltyReceiver (address): 0xA3097F1dF53cc1d55E0Ba7F2299811fE4940e24D
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000a77a68e1e3820b36066496084a8b872c27b312a7
Arg [1] : 000000000000000000000000a3097f1df53cc1d55e0ba7f2299811fe4940e24d
Deployed Bytecode Sourcemap
141567:8088:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;149420:232;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;107514:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108686:158;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108505:115;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;141676:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;141633:36;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109355:588;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;130802:673;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;141709:41;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110014:134;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;141983:48;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;107327:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;107052:213;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;137451:103;;;:::i;:::-;;142038:41;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;136776:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;107674:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108916:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;110219:236;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;145812:1077;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;141775:44;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;143884:1920;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;142348:1486;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;141931:45;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;149128:198;;;:::i;:::-;;109133:155;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;137709:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;148807:276;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;149420:232;149578:4;149608:36;149632:11;149608:23;:36::i;:::-;149601:43;;149420:232;;;:::o;107514:91::-;107559:13;107592:5;107585:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107514:91;:::o;108686:158::-;108753:7;108773:22;108787:7;108773:13;:22::i;:::-;;108815:21;108828:7;108815:12;:21::i;:::-;108808:28;;108686:158;;;:::o;108505:115::-;108577:35;108586:2;108590:7;108599:12;:10;:12::i;:::-;108577:8;:35::i;:::-;108505:115;;:::o;141676:26::-;;;;:::o;141633:36::-;;;;;;;;;;;;;:::o;109355:588::-;109464:1;109450:16;;:2;:16;;;109446:89;;109520:1;109490:33;;;;;;;;;;;:::i;:::-;;;;;;;;109446:89;109756:21;109780:34;109788:2;109792:7;109801:12;:10;:12::i;:::-;109780:7;:34::i;:::-;109756:58;;109846:4;109829:21;;:13;:21;;;109825:111;;109895:4;109901:7;109910:13;109874:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;109825:111;109435:508;109355:588;;;:::o;130802:673::-;130913:16;130931:14;130958:32;130993:17;:26;131011:7;130993:26;;;;;;;;;;;130958:61;;131030:23;131056:12;:21;;;;;;;;;;;;131030:47;;131088:22;131113:12;:28;;;;;;;;;;;;131088:53;;131185:1;131158:29;;:15;:29;;;131154:176;;131222:19;:28;;;;;;;;;;;;131204:46;;131283:19;:35;;;;;;;;;;;;131265:53;;131154:176;131342:21;131398:17;:15;:17::i;:::-;131366:49;;131379:15;131367:27;;:9;:27;;;;:::i;:::-;131366:49;;;;:::i;:::-;131342:73;;131436:15;131453:13;131428:39;;;;;;;;130802:673;;;;;:::o;141709:41::-;141746:4;141709:41;:::o;110014:134::-;110101:39;110118:4;110124:2;110128:7;110101:39;;;;;;;;;;;;:16;:39::i;:::-;110014:134;;;:::o;141983:48::-;;;;;;;;;;;;;;;;;;;;;;:::o;107327:120::-;107390:7;107417:22;107431:7;107417:13;:22::i;:::-;107410:29;;107327:120;;;:::o;107052:213::-;107115:7;107156:1;107139:19;;:5;:19;;;107135:89;;107209:1;107182:30;;;;;;;;;;;:::i;:::-;;;;;;;;107135:89;107241:9;:16;107251:5;107241:16;;;;;;;;;;;;;;;;107234:23;;107052:213;;;:::o;137451:103::-;136662:13;:11;:13::i;:::-;137516:30:::1;137543:1;137516:18;:30::i;:::-;137451:103::o:0;142038:41::-;;;;;;;;;;;;;;;;;:::o;136776:87::-;136822:7;136849:6;;;;;;;;;;;136842:13;;136776:87;:::o;107674:95::-;107721:13;107754:7;107747:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107674:95;:::o;108916:146::-;109002:52;109021:12;:10;:12::i;:::-;109035:8;109045;109002:18;:52::i;:::-;108916:146;;:::o;110219:236::-;110333:31;110346:4;110352:2;110356:7;110333:12;:31::i;:::-;110375:72;110409:12;:10;:12::i;:::-;110423:4;110429:2;110433:7;110442:4;110375:33;:72::i;:::-;110219:236;;;;:::o;145812:1077::-;145877:13;145903:16;145911:7;145903;:16::i;:::-;;145964:20;145987:11;:20;145999:7;145987:20;;;;;;;;;;;145964:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;146018:17;146038:1;146018:21;;146051:19;146073:6;:11;;;146051:33;;146095:20;146118:6;:12;;;146095:35;;146141:21;146165:6;:13;;;146141:37;;146189:17;146209:62;146219:9;146230:11;146243:12;146257:13;146209:9;:62::i;:::-;146189:82;;146282:24;146309:65;146322:9;146333:11;146346:12;146360:13;146309:12;:65::i;:::-;146282:92;;146385:18;146464:17;146473:7;146464:8;:17::i;:::-;146686:25;146706:3;146686:13;:25::i;:::-;146750:10;146413:364;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;146385:393;;146853:26;146873:4;146853:13;:26::i;:::-;146803:77;;;;;;;;:::i;:::-;;;;;;;;;;;;;146789:92;;;;;;;;;;145812:1077;;;:::o;141775:44::-;141816:3;141775:44;:::o;143884:1920::-;143967:16;136662:13;:11;:13::i;:::-;144015:1:::1;144004:8;:12;:42;;;;;141816:3;144020:8;:26;;144004:42;143996:89;;;;;;;;;;;;:::i;:::-;;;;;;;;;141746:4;144118:8;144104:11;;:22;;;;:::i;:::-;:36;;144096:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;144192:25;144234:8;144220:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;144192:51;;144261:9;144273:1;144261:13;;144256:1513;144280:8;144276:1;:12;144256:1513;;;144310:6;:18;144317:10;144310:18;;;;;;;;;;;;;;;;:20;;;;;;;;;:::i;:::-;;;;;;144345:15;144363:1;144345:19;;144379:10;144392:5;144379:18;;144412:19;144446:20;144481:21;144519:932;144527:5;144526:6;:22;;;;;144546:2;144536:7;:12;144526:22;144519:932;;;144569:12;144644:1;144629:12;:16;;;;:::i;:::-;144619:27;144648:10;144660:6;:18;144667:10;144660:18;;;;;;;;;;;;;;;;144680:7;144602:86;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;144592:97;;;;;;144584:106;;144569:121;;144709:16;144763:4;144746:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;144736:41;;;;;;144728:50;;144709:69;;144797:17;144852:4;144835:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;144825:42;;;;;;144817:51;;144797:71;;144887:18;144943:4;144926:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;144916:43;;;;;;144908:52;;144887:73;;145004:3;144993:8;:14;;;;:::i;:::-;144979:28;;145053:2;145041:9;:14;;;;:::i;:::-;145026:29;;145103:2;145090:10;:15;;;;:::i;:::-;145074:31;;145124:17;145171:11;145184:12;145198:13;145154:58;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;145144:69;;;;;;145124:89;;145237:16;:27;145254:9;145237:27;;;;;;;;;;;;;;;;;;;;;145232:204;;145319:4;145289:16;:27;145306:9;145289:27;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;145354:4;145346:12;;145232:204;;;145407:9;;;;;:::i;:::-;;;;145232:204;144550:901;;;;;144519:932;;;145473:5;145465:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;145545:11;;:13;;;;;;;;;:::i;:::-;;;;;;145573:15;145591:11;;145573:29;;145640:48;;;;;;;;145647:11;145640:48;;;;145660:12;145640:48;;;;145674:13;145640:48;;::::0;145617:11:::1;:20;145629:7;145617:20;;;;;;;;;;;:71;;;;;;;;;;;;;;;;;;;;;;;;;;;145703:18;145709:2;145713:7;145703:5;:18::i;:::-;145750:7;145736:8;145745:1;145736:11;;;;;;;;:::i;:::-;;;;;;;:21;;;::::0;::::1;144295:1474;;;;;;144290:3;;;;;;;144256:1513;;;;145788:8;145781:15;;;143884:1920:::0;;;;:::o;142348:1486::-;142408:7;136662:13;:11;:13::i;:::-;141746:4:::1;142436:11;;:24;142428:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;142494:6;:18;142501:10;142494:18;;;;;;;;;;;;;;;;:20;;;;;;;;;:::i;:::-;;;;;;142525:15;142543:1;142525:19;;142555:10;142568:5;142555:18;;142584:19;142614:20;142645:21;142679:872;142687:5;142686:6;:22;;;;;142706:2;142696:7;:12;142686:22;142679:872;;;142725:12;142800:1;142785:12;:16;;;;:::i;:::-;142775:27;142804:10;142816:6;:18;142823:10;142816:18;;;;;;;;;;;;;;;;142836:7;142758:86;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;142748:97;;;;;;142740:106;;142725:121;;142861:16;142915:4;142898:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;142888:41;;;;;;142880:50;;142861:69;;142945:17;143000:4;142983:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;142973:42;;;;;;142965:51;;142945:71;;143031:18;143087:4;143070:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;143060:43;;;;;;143052:52;;143031:73;;143144:3;143133:8;:14;;;;:::i;:::-;143119:28;;143189:2;143177:9;:14;;;;:::i;:::-;143162:29;;143235:2;143222:10;:15;;;;:::i;:::-;143206:31;;143252:17;143299:11;143312:12;143326:13;143282:58;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;143272:69;;;;;;143252:89;;143361:16;:27;143378:9;143361:27;;;;;;;;;;;;;;;;;;;;;143356:184;;143439:4;143409:16;:27;143426:9;143409:27;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;143470:4;143462:12;;143356:184;;;143515:9;;;;;:::i;:::-;;;;143356:184;142710:841;;;;;142679:872;;;143569:5;143561:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;143637:11;;:13;;;;;;;;;:::i;:::-;;;;;;143661:15;143679:11;;143661:29;;143724:48;;;;;;;;143731:11;143724:48;;;;143744:12;143724:48;;;;143758:13;143724:48;;::::0;143701:11:::1;:20;143713:7;143701:20;;;;;;;;;;;:71;;;;;;;;;;;;;;;;;;;;;;;;;;;143783:18;143789:2;143793:7;143783:5;:18::i;:::-;143819:7;143812:14;;;;;;;;142348:1486:::0;;;:::o;141931:45::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;149128:198::-;136662:13;:11;:13::i;:::-;149181:15:::1;149199:21;149181:39;;149249:1;149239:7;:11;149231:42;;;;;;;;;;;;:::i;:::-;;;;;;;;;149292:7;:5;:7::i;:::-;149284:25;;:34;149310:7;149284:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;149170:156;149128:198::o:0;109133:155::-;109221:4;109245:18;:25;109264:5;109245:25;;;;;;;;;;;;;;;:35;109271:8;109245:35;;;;;;;;;;;;;;;;;;;;;;;;;109238:42;;109133:155;;;;:::o;137709:220::-;136662:13;:11;:13::i;:::-;137814:1:::1;137794:22;;:8;:22;;::::0;137790:93:::1;;137868:1;137840:31;;;;;;;;;;;:::i;:::-;;;;;;;;137790:93;137893:28;137912:8;137893:18;:28::i;:::-;137709:220:::0;:::o;148807:276::-;136662:13;:11;:13::i;:::-;148882:12:::1;148904;148882:35;;148928:15;148946:5;:15;;;148970:4;148946:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;148928:48;;149005:1;148995:7;:11;148987:45;;;;;;;;;;;;:::i;:::-;;;;;;;;;149043:5;:14;;;149058:7;:5;:7::i;:::-;149067;149043:32;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;148871:212;;148807:276:::0;:::o;134929:170::-;135031:4;135055:36;135079:11;135055:23;:36::i;:::-;135048:43;;134929:170;;;:::o;121737:247::-;121800:7;121820:13;121836:17;121845:7;121836:8;:17::i;:::-;121820:33;;121885:1;121868:19;;:5;:19;;;121864:90;;121934:7;121911:31;;;;;;;;;;;:::i;:::-;;;;;;;;121864:90;121971:5;121964:12;;;121737:247;;;:::o;111218:129::-;111288:7;111315:15;:24;111331:7;111315:24;;;;;;;;;;;;;;;;;;;;;111308:31;;111218:129;;;:::o;17202:98::-;17255:7;17282:10;17275:17;;17202:98;:::o;119969:122::-;120050:33;120059:2;120063:7;120072:4;120078;120050:8;:33::i;:::-;119969:122;;;:::o;114179:824::-;114265:7;114285:12;114300:17;114309:7;114300:8;:17::i;:::-;114285:32;;114396:1;114380:18;;:4;:18;;;114376:88;;114415:37;114432:4;114438;114444:7;114415:16;:37::i;:::-;114376:88;114527:1;114511:18;;:4;:18;;;114507:263;;114629:48;114646:1;114650:7;114667:1;114671:5;114629:8;:48::i;:::-;114742:1;114723:9;:15;114733:4;114723:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;114507:263;114800:1;114786:16;;:2;:16;;;114782:111;;114865:1;114848:9;:13;114858:2;114848:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;114782:111;114924:2;114905:7;:16;114913:7;114905:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;114963:7;114959:2;114944:27;;114953:4;114944:27;;;;;;;;;;;;114991:4;114984:11;;;114179:824;;;;;:::o;131757:97::-;131815:6;131841:5;131834:12;;131757:97;:::o;136941:166::-;137012:12;:10;:12::i;:::-;137001:23;;:7;:5;:7::i;:::-;:23;;;136997:103;;137075:12;:10;:12::i;:::-;137048:40;;;;;;;;;;;:::i;:::-;;;;;;;;136997:103;136941:166::o;138089:191::-;138163:16;138182:6;;;;;;;;;;;138163:25;;138208:8;138199:6;;:17;;;;;;;;;;;;;;;;;;138263:8;138232:40;;138253:8;138232:40;;;;;;;;;;;;138152:128;138089:191;:::o;121176:318::-;121304:1;121284:22;;:8;:22;;;121280:93;;121352:8;121330:31;;;;;;;;;;;:::i;:::-;;;;;;;;121280:93;121421:8;121383:18;:25;121402:5;121383:25;;;;;;;;;;;;;;;:35;121409:8;121383:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;121467:8;121445:41;;121460:5;121445:41;;;121477:8;121445:41;;;;;;:::i;:::-;;;;;;;;121176:318;;;:::o;15552:948::-;15756:1;15739:2;:14;;;:18;15735:758;;;15794:2;15778:36;;;15815:8;15825:4;15831:7;15840:4;15778:67;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;15774:708;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16158:1;16141:6;:13;:18;16137:330;;16283:2;16247:39;;;;;;;;;;;:::i;:::-;;;;;;;;16137:330;16417:6;16411:13;16402:6;16398:2;16394:15;16387:38;15774:708;15903:41;;;15893:51;;;:6;:51;;;;15889:185;;16051:2;16015:39;;;;;;;;;;;:::i;:::-;;;;;;;;15889:185;15846:243;15735:758;15552:948;;;;;:::o;146897:756::-;147067:13;147093:19;147115:10;;;;;;;;;;;:22;;;147138:1;147141:9;147115:36;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;147093:58;;147162:23;147188:10;;;;;;;;;;;:22;;;147211:1;147214:13;147188:40;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;147162:66;;147239:21;147263:10;;;;;;;;;;;:22;;;147286:1;147289:11;147263:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;147239:62;;147312:22;147337:10;;;;;;;;;;;:22;;;147360:1;147363:12;147337:39;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;147312:64;;147536:5;147556:9;147580:7;147602:8;147401:243;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;147387:258;;;;;;146897:756;;;;;;:::o;147661:592::-;147834:13;147860:20;147883:10;;;;;;;;;;;:24;;;147908:1;147911:9;147883:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;147860:61;;147965:6;147978:10;;;;;;;;;;;:24;;;148003:1;148006:11;147978:40;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;147948:71;;;;;;;;;:::i;:::-;;;;;;;;;;;;;147932:88;;148064:6;148077:10;;;;;;;;;;;:24;;;148102:1;148105:12;148077:41;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;148047:72;;;;;;;;;:::i;:::-;;;;;;;;;;;;;148031:89;;148164:6;148177:10;;;;;;;;;;;:24;;;148202:1;148205:13;148177:42;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;148147:73;;;;;;;;;:::i;:::-;;;;;;;;;;;;;148131:90;;148239:6;148232:13;;;147661:592;;;;;;:::o;148261:496::-;148317:13;148356:1;148347:5;:10;148343:26;;148359:10;;;;;;;;;;;;;;;;;;;;;148343:26;148380:12;148395:5;148380:20;;148411:14;148436:78;148451:1;148443:4;:9;148436:78;;148469:8;;;;;:::i;:::-;;;;148500:2;148492:10;;;;;:::i;:::-;;;148436:78;;;148524:19;148556:6;148546:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;148524:39;;148574:144;148590:1;148581:5;:10;148574:144;;148608:8;;;;;:::i;:::-;;;;148675:2;148667:5;:10;;;;:::i;:::-;148661:2;:17;;;;:::i;:::-;148648:32;;148631:6;148638;148631:14;;;;;;;;:::i;:::-;;;;;:49;;;;;;;;;;;148704:2;148695:11;;;;;:::i;:::-;;;148574:144;;;148742:6;148728:21;;;;;148261:496;;;;:::o;122695:126::-;122753:13;122786:27;122794:4;122800:6;;;;;;;;;;;;;;;;;122808:4;122786:7;:27::i;:::-;122779:34;;122695:126;;;:::o;115339:335::-;115421:1;115407:16;;:2;:16;;;115403:89;;115477:1;115447:33;;;;;;;;;;;:::i;:::-;;;;;;;;115403:89;115502:21;115526:32;115534:2;115538:7;115555:1;115526:7;:32::i;:::-;115502:56;;115598:1;115573:27;;:13;:27;;;115569:98;;115652:1;115624:31;;;;;;;;;;;:::i;:::-;;;;;;;;115569:98;115392:282;115339:335;;:::o;106683:305::-;106785:4;106837:25;106822:40;;;:11;:40;;;;:105;;;;106894:33;106879:48;;;:11;:48;;;;106822:105;:158;;;;106944:36;106968:11;106944:23;:36::i;:::-;106822:158;106802:178;;106683:305;;;:::o;110980:117::-;111046:7;111073;:16;111081:7;111073:16;;;;;;;;;;;;;;;;;;;;;111066:23;;110980:117;;;:::o;120279:678::-;120441:9;:31;;;;120470:1;120454:18;;:4;:18;;;;120441:31;120437:471;;;120489:13;120505:22;120519:7;120505:13;:22::i;:::-;120489:38;;120674:1;120658:18;;:4;:18;;;;:35;;;;;120689:4;120680:13;;:5;:13;;;;120658:35;:69;;;;;120698:29;120715:5;120722:4;120698:16;:29::i;:::-;120697:30;120658:69;120654:144;;;120777:4;120755:27;;;;;;;;;;;:::i;:::-;;;;;;;;120654:144;120818:9;120814:83;;;120873:7;120869:2;120853:28;;120862:5;120853:28;;;;;;;;;;;;120814:83;120474:434;120437:471;120947:2;120920:15;:24;120936:7;120920:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;120279:678;;;;:::o;112386:376::-;112499:38;112513:5;112520:7;112529;112499:13;:38::i;:::-;112494:261;;112575:1;112558:19;;:5;:19;;;112554:190;;112628:7;112605:31;;;;;;;;;;;:::i;:::-;;;;;;;;112554:190;112711:7;112720;112684:44;;;;;;;;;;;;:::i;:::-;;;;;;;;112494:261;112386:376;;;:::o;123233:4109::-;123330:13;123582:1;123567:4;:11;:16;123563:31;;123585:9;;;;;;;;;;;;;;;;123563:31;124547:20;124570:11;:69;;124638:1;124633;124619:4;:11;124615:1;:15;;;;:::i;:::-;:19;;;;:::i;:::-;124614:25;;;;:::i;:::-;124570:69;;;124609:1;124604;124590:4;:11;:15;;;;:::i;:::-;124589:21;;;;:::i;:::-;124584:1;:27;;;;:::i;:::-;124570:69;124547:92;;124652:20;124686:12;124675:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124652:47;;124851:1;124844:5;124840:13;124955:4;124947:6;124943:17;124989:4;125037;125031:11;125025:4;125021:22;125289:4;125281:6;125277:17;125332:8;125326:15;125372:4;125362:8;125355:22;125447:1286;125482:6;125473:7;125470:19;125447:1286;;;125588:1;125579:7;125575:15;125564:26;;125627:7;125621:14;126223:4;126215:5;126211:2;126207:14;126203:25;126193:8;126189:40;126183:47;126172:9;126164:67;126277:1;126266:9;126262:17;126249:30;;126369:4;126361:5;126357:2;126353:14;126349:25;126339:8;126335:40;126329:47;126318:9;126310:67;126423:1;126412:9;126408:17;126395:30;;126514:4;126506:5;126503:1;126499:13;126495:24;126485:8;126481:39;126475:46;126464:9;126456:66;126568:1;126557:9;126553:17;126540:30;;126651:4;126644:5;126640:16;126630:8;126626:31;126620:38;126609:9;126601:58;126705:1;126694:9;126690:17;126677:30;;125509:1224;125447:1286;;;126814:10;126804:8;126797:28;126844:11;126841:457;;;127029:1;127022:4;127016:11;127012:19;127054:1;127049:135;;;;127207:1;127202:81;;;;127005:278;;127049:135;127106:4;127102:1;127091:9;127087:17;127079:32;127160:4;127156:1;127145:9;127141:17;127133:32;127049:135;;127202:81;127259:4;127255:1;127244:9;127240:17;127232:32;127005:278;;126841:457;124737:2572;;;;;;127328:6;127321:13;;;;123233:4109;;;;;;:::o;130532:215::-;130634:4;130673:26;130658:41;;;:11;:41;;;;:81;;;;130703:36;130727:11;130703:23;:36::i;:::-;130658:81;130651:88;;130532:215;;;:::o;111667:276::-;111770:4;111826:1;111807:21;;:7;:21;;;;:128;;;;;111855:7;111846:16;;:5;:16;;;:52;;;;111866:32;111883:5;111890:7;111866:16;:32::i;:::-;111846:52;:88;;;;111927:7;111902:32;;:21;111915:7;111902:12;:21::i;:::-;:32;;;111846:88;111807:128;111787:148;;111667:276;;;;;:::o;105281:148::-;105357:4;105396:25;105381:40;;;:11;:40;;;;105374:47;;105281:148;;;:::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:118::-;4870:24;4888:5;4870:24;:::i;:::-;4865:3;4858:37;4783:118;;:::o;4907:222::-;5000:4;5038:2;5027:9;5023:18;5015:26;;5051:71;5119:1;5108:9;5104:17;5095:6;5051:71;:::i;:::-;4907:222;;;;:::o;5135:60::-;5163:3;5184:5;5177:12;;5135:60;;;:::o;5201:142::-;5251:9;5284:53;5302:34;5311:24;5329:5;5311:24;:::i;:::-;5302:34;:::i;:::-;5284:53;:::i;:::-;5271:66;;5201:142;;;:::o;5349:126::-;5399:9;5432:37;5463:5;5432:37;:::i;:::-;5419:50;;5349:126;;;:::o;5481:153::-;5558:9;5591:37;5622:5;5591:37;:::i;:::-;5578:50;;5481:153;;;:::o;5640:185::-;5754:64;5812:5;5754:64;:::i;:::-;5749:3;5742:77;5640:185;;:::o;5831:276::-;5951:4;5989:2;5978:9;5974:18;5966:26;;6002:98;6097:1;6086:9;6082:17;6073:6;6002:98;:::i;:::-;5831:276;;;;:::o;6113:619::-;6190:6;6198;6206;6255:2;6243:9;6234:7;6230:23;6226:32;6223:119;;;6261:79;;:::i;:::-;6223:119;6381:1;6406:53;6451:7;6442:6;6431:9;6427:22;6406:53;:::i;:::-;6396:63;;6352:117;6508:2;6534:53;6579:7;6570:6;6559:9;6555:22;6534:53;:::i;:::-;6524:63;;6479:118;6636:2;6662:53;6707:7;6698:6;6687:9;6683:22;6662:53;:::i;:::-;6652:63;;6607:118;6113:619;;;;;:::o;6738:474::-;6806:6;6814;6863:2;6851:9;6842:7;6838:23;6834:32;6831:119;;;6869:79;;:::i;:::-;6831:119;6989:1;7014:53;7059:7;7050:6;7039:9;7035:22;7014:53;:::i;:::-;7004:63;;6960:117;7116:2;7142:53;7187:7;7178:6;7167:9;7163:22;7142:53;:::i;:::-;7132:63;;7087:118;6738:474;;;;;:::o;7218:332::-;7339:4;7377:2;7366:9;7362:18;7354:26;;7390:71;7458:1;7447:9;7443:17;7434:6;7390:71;:::i;:::-;7471:72;7539:2;7528:9;7524:18;7515:6;7471:72;:::i;:::-;7218:332;;;;;:::o;7556:77::-;7593:7;7622:5;7611:16;;7556:77;;;:::o;7639:122::-;7712:24;7730:5;7712:24;:::i;:::-;7705:5;7702:35;7692:63;;7751:1;7748;7741:12;7692:63;7639:122;:::o;7767:139::-;7813:5;7851:6;7838:20;7829:29;;7867:33;7894:5;7867:33;:::i;:::-;7767:139;;;;:::o;7912:329::-;7971:6;8020:2;8008:9;7999:7;7995:23;7991:32;7988:119;;;8026:79;;:::i;:::-;7988:119;8146:1;8171:53;8216:7;8207:6;8196:9;8192:22;8171:53;:::i;:::-;8161:63;;8117:117;7912:329;;;;:::o;8247:::-;8306:6;8355:2;8343:9;8334:7;8330:23;8326:32;8323:119;;;8361:79;;:::i;:::-;8323:119;8481:1;8506:53;8551:7;8542:6;8531:9;8527:22;8506:53;:::i;:::-;8496:63;;8452:117;8247:329;;;;:::o;8582:116::-;8652:21;8667:5;8652:21;:::i;:::-;8645:5;8642:32;8632:60;;8688:1;8685;8678:12;8632:60;8582:116;:::o;8704:133::-;8747:5;8785:6;8772:20;8763:29;;8801:30;8825:5;8801:30;:::i;:::-;8704:133;;;;:::o;8843:468::-;8908:6;8916;8965:2;8953:9;8944:7;8940:23;8936:32;8933:119;;;8971:79;;:::i;:::-;8933:119;9091:1;9116:53;9161:7;9152:6;9141:9;9137:22;9116:53;:::i;:::-;9106:63;;9062:117;9218:2;9244:50;9286:7;9277:6;9266:9;9262:22;9244:50;:::i;:::-;9234:60;;9189:115;8843:468;;;;;:::o;9317:117::-;9426:1;9423;9416:12;9440:117;9549:1;9546;9539:12;9563:180;9611:77;9608:1;9601:88;9708:4;9705:1;9698:15;9732:4;9729:1;9722:15;9749:281;9832:27;9854:4;9832:27;:::i;:::-;9824:6;9820:40;9962:6;9950:10;9947:22;9926:18;9914:10;9911:34;9908:62;9905:88;;;9973:18;;:::i;:::-;9905:88;10013:10;10009:2;10002:22;9792:238;9749:281;;:::o;10036:129::-;10070:6;10097:20;;:::i;:::-;10087:30;;10126:33;10154:4;10146:6;10126:33;:::i;:::-;10036:129;;;:::o;10171:307::-;10232:4;10322:18;10314:6;10311:30;10308:56;;;10344:18;;:::i;:::-;10308:56;10382:29;10404:6;10382:29;:::i;:::-;10374:37;;10466:4;10460;10456:15;10448:23;;10171:307;;;:::o;10484:148::-;10582:6;10577:3;10572;10559:30;10623:1;10614:6;10609:3;10605:16;10598:27;10484:148;;;:::o;10638:423::-;10715:5;10740:65;10756:48;10797:6;10756:48;:::i;:::-;10740:65;:::i;:::-;10731:74;;10828:6;10821:5;10814:21;10866:4;10859:5;10855:16;10904:3;10895:6;10890:3;10886:16;10883:25;10880:112;;;10911:79;;:::i;:::-;10880:112;11001:54;11048:6;11043:3;11038;11001:54;:::i;:::-;10721:340;10638:423;;;;;:::o;11080:338::-;11135:5;11184:3;11177:4;11169:6;11165:17;11161:27;11151:122;;11192:79;;:::i;:::-;11151:122;11309:6;11296:20;11334:78;11408:3;11400:6;11393:4;11385:6;11381:17;11334:78;:::i;:::-;11325:87;;11141:277;11080:338;;;;:::o;11424:943::-;11519:6;11527;11535;11543;11592:3;11580:9;11571:7;11567:23;11563:33;11560:120;;;11599:79;;:::i;:::-;11560:120;11719:1;11744:53;11789:7;11780:6;11769:9;11765:22;11744:53;:::i;:::-;11734:63;;11690:117;11846:2;11872:53;11917:7;11908:6;11897:9;11893:22;11872:53;:::i;:::-;11862:63;;11817:118;11974:2;12000:53;12045:7;12036:6;12025:9;12021:22;12000:53;:::i;:::-;11990:63;;11945:118;12130:2;12119:9;12115:18;12102:32;12161:18;12153:6;12150:30;12147:117;;;12183:79;;:::i;:::-;12147:117;12288:62;12342:7;12333:6;12322:9;12318:22;12288:62;:::i;:::-;12278:72;;12073:287;11424:943;;;;;;;:::o;12373:114::-;12440:6;12474:5;12468:12;12458:22;;12373:114;;;:::o;12493:184::-;12592:11;12626:6;12621:3;12614:19;12666:4;12661:3;12657:14;12642:29;;12493:184;;;;:::o;12683:132::-;12750:4;12773:3;12765:11;;12803:4;12798:3;12794:14;12786:22;;12683:132;;;:::o;12821:108::-;12898:24;12916:5;12898:24;:::i;:::-;12893:3;12886:37;12821:108;;:::o;12935:179::-;13004:10;13025:46;13067:3;13059:6;13025:46;:::i;:::-;13103:4;13098:3;13094:14;13080:28;;12935:179;;;;:::o;13120:113::-;13190:4;13222;13217:3;13213:14;13205:22;;13120:113;;;:::o;13269:732::-;13388:3;13417:54;13465:5;13417:54;:::i;:::-;13487:86;13566:6;13561:3;13487:86;:::i;:::-;13480:93;;13597:56;13647:5;13597:56;:::i;:::-;13676:7;13707:1;13692:284;13717:6;13714:1;13711:13;13692:284;;;13793:6;13787:13;13820:63;13879:3;13864:13;13820:63;:::i;:::-;13813:70;;13906:60;13959:6;13906:60;:::i;:::-;13896:70;;13752:224;13739:1;13736;13732:9;13727:14;;13692:284;;;13696:14;13992:3;13985:10;;13393:608;;;13269:732;;;;:::o;14007:373::-;14150:4;14188:2;14177:9;14173:18;14165:26;;14237:9;14231:4;14227:20;14223:1;14212:9;14208:17;14201:47;14265:108;14368:4;14359:6;14265:108;:::i;:::-;14257:116;;14007:373;;;;:::o;14386:442::-;14535:4;14573:2;14562:9;14558:18;14550:26;;14586:71;14654:1;14643:9;14639:17;14630:6;14586:71;:::i;:::-;14667:72;14735:2;14724:9;14720:18;14711:6;14667:72;:::i;:::-;14749;14817:2;14806:9;14802:18;14793:6;14749:72;:::i;:::-;14386:442;;;;;;:::o;14834:474::-;14902:6;14910;14959:2;14947:9;14938:7;14934:23;14930:32;14927:119;;;14965:79;;:::i;:::-;14927:119;15085:1;15110:53;15155:7;15146:6;15135:9;15131:22;15110:53;:::i;:::-;15100:63;;15056:117;15212:2;15238:53;15283:7;15274:6;15263:9;15259:22;15238:53;:::i;:::-;15228:63;;15183:118;14834:474;;;;;:::o;15314:180::-;15362:77;15359:1;15352:88;15459:4;15456:1;15449:15;15483:4;15480:1;15473:15;15500:320;15544:6;15581:1;15575:4;15571:12;15561:22;;15628:1;15622:4;15618:12;15649:18;15639:81;;15705:4;15697:6;15693:17;15683:27;;15639:81;15767:2;15759:6;15756:14;15736:18;15733:38;15730:84;;15786:18;;:::i;:::-;15730:84;15551:269;15500:320;;;:::o;15826:442::-;15975:4;16013:2;16002:9;15998:18;15990:26;;16026:71;16094:1;16083:9;16079:17;16070:6;16026:71;:::i;:::-;16107:72;16175:2;16164:9;16160:18;16151:6;16107:72;:::i;:::-;16189;16257:2;16246:9;16242:18;16233:6;16189:72;:::i;:::-;15826:442;;;;;;:::o;16274:180::-;16322:77;16319:1;16312:88;16419:4;16416:1;16409:15;16443:4;16440:1;16433:15;16460:410;16500:7;16523:20;16541:1;16523:20;:::i;:::-;16518:25;;16557:20;16575:1;16557:20;:::i;:::-;16552:25;;16612:1;16609;16605:9;16634:30;16652:11;16634:30;:::i;:::-;16623:41;;16813:1;16804:7;16800:15;16797:1;16794:22;16774:1;16767:9;16747:83;16724:139;;16843:18;;:::i;:::-;16724:139;16508:362;16460:410;;;;:::o;16876:180::-;16924:77;16921:1;16914:88;17021:4;17018:1;17011:15;17045:4;17042:1;17035:15;17062:185;17102:1;17119:20;17137:1;17119:20;:::i;:::-;17114:25;;17153:20;17171:1;17153:20;:::i;:::-;17148:25;;17192:1;17182:35;;17197:18;;:::i;:::-;17182:35;17239:1;17236;17232:9;17227:14;;17062:185;;;;:::o;17253:148::-;17355:11;17392:3;17377:18;;17253:148;;;;:::o;17407:214::-;17547:66;17543:1;17535:6;17531:14;17524:90;17407:214;:::o;17627:402::-;17787:3;17808:85;17890:2;17885:3;17808:85;:::i;:::-;17801:92;;17902:93;17991:3;17902:93;:::i;:::-;18020:2;18015:3;18011:12;18004:19;;17627:402;;;:::o;18035:390::-;18141:3;18169:39;18202:5;18169:39;:::i;:::-;18224:89;18306:6;18301:3;18224:89;:::i;:::-;18217:96;;18322:65;18380:6;18375:3;18368:4;18361:5;18357:16;18322:65;:::i;:::-;18412:6;18407:3;18403:16;18396:23;;18145:280;18035:390;;;;:::o;18431:214::-;18571:66;18567:1;18559:6;18555:14;18548:90;18431:214;:::o;18651:400::-;18811:3;18832:84;18914:1;18909:3;18832:84;:::i;:::-;18825:91;;18925:93;19014:3;18925:93;:::i;:::-;19043:1;19038:3;19034:11;19027:18;;18651:400;;;:::o;19057:453::-;19197:66;19193:1;19185:6;19181:14;19174:90;19298:34;19293:2;19285:6;19281:15;19274:59;19367:34;19362:2;19354:6;19350:15;19343:59;19436:66;19431:2;19423:6;19419:15;19412:91;19057:453;:::o;19516:404::-;19676:3;19697:86;19779:3;19774;19697:86;:::i;:::-;19690:93;;19792;19881:3;19792:93;:::i;:::-;19910:3;19905;19901:13;19894:20;;19516:404;;;:::o;19926:254::-;20066:66;20062:1;20054:6;20050:14;20043:90;20167:5;20162:2;20154:6;20150:15;20143:30;19926:254;:::o;20186:402::-;20346:3;20367:85;20449:2;20444:3;20367:85;:::i;:::-;20360:92;;20461:93;20550:3;20461:93;:::i;:::-;20579:2;20574:3;20570:12;20563:19;;20186:402;;;:::o;20594:214::-;20734:66;20730:1;20722:6;20718:14;20711:90;20594:214;:::o;20814:402::-;20974:3;20995:85;21077:2;21072:3;20995:85;:::i;:::-;20988:92;;21089:93;21178:3;21089:93;:::i;:::-;21207:2;21202:3;21198:12;21191:19;;20814:402;;;:::o;21222:144::-;21358:4;21354:1;21346:6;21342:14;21335:28;21222:144;:::o;21368:384::-;21528:3;21545:84;21627:1;21622:3;21545:84;:::i;:::-;21538:91;;21634:93;21723:3;21634:93;:::i;:::-;21748:1;21743:3;21739:11;21732:18;;21368:384;;;:::o;21754:2409::-;22689:3;22707:148;22851:3;22707:148;:::i;:::-;22700:155;;22868:95;22959:3;22950:6;22868:95;:::i;:::-;22861:102;;22976:148;23120:3;22976:148;:::i;:::-;22969:155;;23137:148;23281:3;23137:148;:::i;:::-;23130:155;;23298:148;23442:3;23298:148;:::i;:::-;23291:155;;23459:95;23550:3;23541:6;23459:95;:::i;:::-;23452:102;;23567:148;23711:3;23567:148;:::i;:::-;23560:155;;23728:148;23872:3;23728:148;:::i;:::-;23721:155;;23889:95;23980:3;23971:6;23889:95;:::i;:::-;23882:102;;23997:148;24141:3;23997:148;:::i;:::-;23990:155;;24158:3;24151:10;;21754:2409;;;;;;:::o;24165:171::-;24301:31;24297:1;24289:6;24285:14;24278:55;24165:171;:::o;24338:386::-;24498:3;24515:85;24597:2;24592:3;24515:85;:::i;:::-;24508:92;;24605:93;24694:3;24605:93;:::i;:::-;24719:2;24714:3;24710:12;24703:19;;24338:386;;;:::o;24726:525::-;24959:3;24977:148;25121:3;24977:148;:::i;:::-;24970:155;;25138:95;25229:3;25220:6;25138:95;:::i;:::-;25131:102;;25246:3;25239:10;;24726:525;;;;:::o;25253:209::-;25389:34;25385:1;25377:6;25373:14;25366:58;25454:4;25449:2;25441:6;25437:15;25430:29;25253:209;:::o;25464:350::-;25606:3;25623:67;25687:2;25682:3;25623:67;:::i;:::-;25616:74;;25695:93;25784:3;25695:93;:::i;:::-;25809:2;25804:3;25800:12;25793:19;;25464:350;;;:::o;25816:403::-;25982:4;26016:2;26005:9;26001:18;25993:26;;26061:9;26055:4;26051:20;26047:1;26036:9;26032:17;26025:47;26085:131;26211:4;26085:131;:::i;:::-;26077:139;;25816:403;;;:::o;26221:171::-;26261:3;26276:20;26294:1;26276:20;:::i;:::-;26271:25;;26306:20;26324:1;26306:20;:::i;:::-;26301:25;;26345:1;26342;26338:9;26331:16;;26362:3;26359:1;26356:10;26353:36;;;26369:18;;:::i;:::-;26353:36;26221:171;;;;:::o;26394:209::-;26530:34;26526:1;26518:6;26514:14;26507:58;26595:4;26590:2;26582:6;26578:15;26571:29;26394:209;:::o;26605:350::-;26747:3;26764:67;26828:2;26823:3;26764:67;:::i;:::-;26757:74;;26836:93;26925:3;26836:93;:::i;:::-;26950:2;26945:3;26941:12;26934:19;;26605:350;;;:::o;26957:403::-;27123:4;27157:2;27146:9;27142:18;27134:26;;27202:9;27196:4;27192:20;27188:1;27177:9;27173:17;27166:47;27226:131;27352:4;27226:131;:::i;:::-;27218:139;;26957:403;;;:::o;27362:217::-;27401:3;27420:24;27438:5;27420:24;:::i;:::-;27411:33;;27462:66;27455:5;27452:77;27449:103;;27532:18;;:::i;:::-;27449:103;27575:1;27568:5;27564:13;27557:20;;27362:217;;;:::o;27581:174::-;27621:4;27637:20;27655:1;27637:20;:::i;:::-;27632:25;;27667:20;27685:1;27667:20;:::i;:::-;27662:25;;27707:1;27704;27700:9;27692:17;;27727:1;27721:4;27718:11;27715:37;;;27732:18;;:::i;:::-;27715:37;27581:174;;;;:::o;27757:71::-;27796:7;27821:5;27810:16;;27757:71;;;:::o;27830:149::-;27931:45;27951:24;27969:5;27951:24;:::i;:::-;27931:45;:::i;:::-;27926:3;27919:58;27830:149;;:::o;27981:82::-;28014:8;28054:5;28050:2;28046:14;28029:31;;27981:82;;;:::o;28065:86::-;28104:7;28129:20;28143:5;28129:20;:::i;:::-;28118:31;;28065:86;;;:::o;28153:92::-;28192:7;28217:26;28237:5;28217:26;:::i;:::-;28206:37;;28153:92;;;:::o;28247:149::-;28348:45;28368:24;28386:5;28368:24;:::i;:::-;28348:45;:::i;:::-;28343:3;28336:58;28247:149;;:::o;28398:71::-;28437:7;28462:5;28451:16;;28398:71;;;:::o;28471:149::-;28572:45;28592:24;28610:5;28592:24;:::i;:::-;28572:45;:::i;:::-;28567:3;28560:58;28471:149;;:::o;28622:639::-;28818:3;28829:75;28900:3;28891:6;28829:75;:::i;:::-;28925:2;28920:3;28916:12;28909:19;;28934:75;29005:3;28996:6;28934:75;:::i;:::-;29030:2;29025:3;29021:12;29014:19;;29039:75;29110:3;29101:6;29039:75;:::i;:::-;29135:2;29130:3;29126:12;29119:19;;29144:75;29215:3;29206:6;29144:75;:::i;:::-;29240:2;29235:3;29231:12;29224:19;;29256:3;29249:10;;28622:639;;;;;;;:::o;29263:146::-;29399:6;29395:1;29387:6;29383:14;29376:30;29263:146;:::o;29411:384::-;29571:3;29588:84;29670:1;29665:3;29588:84;:::i;:::-;29581:91;;29677:93;29766:3;29677:93;:::i;:::-;29791:1;29786:3;29782:11;29775:18;;29411:384;;;:::o;29797:502::-;30010:3;30021:75;30092:3;30083:6;30021:75;:::i;:::-;30117:2;30112:3;30108:12;30101:19;;30133:148;30277:3;30133:148;:::i;:::-;30126:155;;30294:3;30287:10;;29797:502;;;;:::o;30301:147::-;30437:7;30433:1;30425:6;30421:14;30414:31;30301:147;:::o;30450:384::-;30610:3;30627:84;30709:1;30704:3;30627:84;:::i;:::-;30620:91;;30716:93;30805:3;30716:93;:::i;:::-;30830:1;30825:3;30821:11;30814:18;;30450:384;;;:::o;30836:502::-;31049:3;31060:75;31131:3;31122:6;31060:75;:::i;:::-;31156:2;31151:3;31147:12;31140:19;;31172:148;31316:3;31172:148;:::i;:::-;31165:155;;31333:3;31326:10;;30836:502;;;;:::o;31340:148::-;31476:8;31472:1;31464:6;31460:14;31453:32;31340:148;:::o;31490:384::-;31650:3;31667:84;31749:1;31744:3;31667:84;:::i;:::-;31660:91;;31756:93;31845:3;31756:93;:::i;:::-;31870:1;31865:3;31861:11;31854:18;;31490:384;;;:::o;31876:502::-;32089:3;32100:75;32171:3;32162:6;32100:75;:::i;:::-;32196:2;32191:3;32187:12;32180:19;;32212:148;32356:3;32212:148;:::i;:::-;32205:155;;32373:3;32366:10;;31876:502;;;;:::o;32380:156::-;32412:1;32425:20;32443:1;32425:20;:::i;:::-;32420:25;;32455:20;32473:1;32455:20;:::i;:::-;32450:25;;32490:1;32480:35;;32495:18;;:::i;:::-;32480:35;32532:1;32529;32525:9;32520:14;;32380:156;;;;:::o;32538:506::-;32706:3;32717:75;32788:3;32779:6;32717:75;:::i;:::-;32813:2;32808:3;32804:12;32797:19;;32822:75;32893:3;32884:6;32822:75;:::i;:::-;32918:2;32913:3;32909:12;32902:19;;32927:75;32998:3;32989:6;32927:75;:::i;:::-;33023:2;33018:3;33014:12;33007:19;;33039:3;33032:10;;32538:506;;;;;;:::o;33046:220::-;33182:34;33178:1;33170:6;33166:14;33159:58;33247:15;33242:2;33234:6;33230:15;33223:40;33046:220;:::o;33268:350::-;33410:3;33427:67;33491:2;33486:3;33427:67;:::i;:::-;33420:74;;33499:93;33588:3;33499:93;:::i;:::-;33613:2;33608:3;33604:12;33597:19;;33268:350;;;:::o;33620:403::-;33786:4;33820:2;33809:9;33805:18;33797:26;;33865:9;33859:4;33855:20;33851:1;33840:9;33836:17;33829:47;33889:131;34015:4;33889:131;:::i;:::-;33881:139;;33620:403;;;:::o;34025:164::-;34069:77;34066:1;34059:88;34162:4;34159:1;34152:15;34182:4;34179:1;34172:15;34191:160;34327:20;34323:1;34315:6;34311:14;34304:44;34191:160;:::o;34353:350::-;34495:3;34512:67;34576:2;34571:3;34512:67;:::i;:::-;34505:74;;34584:93;34673:3;34584:93;:::i;:::-;34698:2;34693:3;34689:12;34682:19;;34353:350;;;:::o;34705:403::-;34871:4;34905:2;34894:9;34890:18;34882:26;;34950:9;34944:4;34940:20;34936:1;34925:9;34921:17;34914:47;34974:131;35100:4;34974:131;:::i;:::-;34966:139;;34705:403;;;:::o;35110:160::-;35246:20;35242:1;35234:6;35230:14;35223:44;35110:160;:::o;35272:350::-;35414:3;35431:67;35495:2;35490:3;35431:67;:::i;:::-;35424:74;;35503:93;35592:3;35503:93;:::i;:::-;35617:2;35612:3;35608:12;35601:19;;35272:350;;;:::o;35624:403::-;35790:4;35824:2;35813:9;35809:18;35801:26;;35869:9;35863:4;35859:20;35855:1;35844:9;35840:17;35833:47;35893:131;36019:4;35893:131;:::i;:::-;35885:139;;35624:403;;;:::o;36029:131::-;36086:5;36113:6;36107:13;36098:22;;36125:33;36152:5;36125:33;:::i;:::-;36029:131;;;;:::o;36162:327::-;36232:6;36277:2;36265:9;36256:7;36252:23;36248:32;36245:119;;;36283:79;;:::i;:::-;36245:119;36395:1;36416:64;36472:7;36463:6;36452:9;36448:22;36416:64;:::i;:::-;36406:74;;36370:116;36162:327;;;;:::o;36491:163::-;36627:23;36623:1;36615:6;36611:14;36604:47;36491:163;:::o;36656:350::-;36798:3;36815:67;36879:2;36874:3;36815:67;:::i;:::-;36808:74;;36887:93;36976:3;36887:93;:::i;:::-;37001:2;36996:3;36992:12;36985:19;;36656:350;;;:::o;37008:403::-;37174:4;37208:2;37197:9;37193:18;37185:26;;37253:9;37247:4;37243:20;37239:1;37228:9;37224:17;37217:47;37277:131;37403:4;37277:131;:::i;:::-;37269:139;;37008:403;;;:::o;37413:125::-;37467:5;37494:6;37488:13;37479:22;;37506:30;37530:5;37506:30;:::i;:::-;37413:125;;;;:::o;37540:321::-;37607:6;37652:2;37640:9;37631:7;37627:23;37623:32;37620:119;;;37658:79;;:::i;:::-;37620:119;37770:1;37791:61;37844:7;37835:6;37824:9;37820:22;37791:61;:::i;:::-;37781:71;;37745:113;37540:321;;;;:::o;37863:90::-;37914:6;37944:5;37938:12;37928:22;;37863:90;;;:::o;37955:156::-;38038:11;38068:6;38063:3;38056:19;38104:4;38099:3;38095:14;38080:29;;37955:156;;;;:::o;38113:353::-;38199:3;38223:38;38255:5;38223:38;:::i;:::-;38273:70;38336:6;38331:3;38273:70;:::i;:::-;38266:77;;38348:65;38406:6;38401:3;38394:4;38387:5;38383:16;38348:65;:::i;:::-;38434:29;38456:6;38434:29;:::i;:::-;38429:3;38425:39;38418:46;;38203:263;38113:353;;;;:::o;38468:612::-;38663:4;38697:3;38686:9;38682:19;38674:27;;38707:71;38775:1;38764:9;38760:17;38751:6;38707:71;:::i;:::-;38784:72;38852:2;38841:9;38837:18;38828:6;38784:72;:::i;:::-;38862;38930:2;38919:9;38915:18;38906:6;38862:72;:::i;:::-;38977:9;38971:4;38967:20;38962:2;38951:9;38947:18;38940:48;39001:76;39072:4;39063:6;39001:76;:::i;:::-;38993:84;;38468:612;;;;;;;:::o;39082:129::-;39138:5;39165:6;39159:13;39150:22;;39177:32;39203:5;39177:32;:::i;:::-;39082:129;;;;:::o;39213:325::-;39282:6;39327:2;39315:9;39306:7;39302:23;39298:32;39295:119;;;39333:79;;:::i;:::-;39295:119;39445:1;39466:63;39521:7;39512:6;39501:9;39497:22;39466:63;:::i;:::-;39456:73;;39420:115;39213:325;;;;:::o;39540:77::-;39585:7;39610:5;39599:16;;39540:77;;;:::o;39619:78::-;39654:7;39690:4;39683:5;39679:16;39668:27;;39619:78;;;:::o;39699:146::-;39755:9;39784:59;39800:42;39809:32;39835:5;39809:32;:::i;:::-;39800:42;:::i;:::-;39784:59;:::i;:::-;39771:72;;39699:146;;;:::o;39847:135::-;39936:43;39973:5;39936:43;:::i;:::-;39931:3;39924:56;39847:135;;:::o;39984:328::-;40111:4;40145:2;40134:9;40130:18;40122:26;;40154:77;40228:1;40217:9;40213:17;40204:6;40154:77;:::i;:::-;40237:72;40305:2;40294:9;40290:18;40281:6;40237:72;:::i;:::-;39984:328;;;;;:::o;40314:284::-;40376:4;40458:18;40450:6;40447:30;40444:56;;;40480:18;;:::i;:::-;40444:56;40514:29;40536:6;40514:29;:::i;:::-;40506:37;;40590:4;40584;40580:15;40572:23;;40314:284;;;:::o;40600:410::-;40689:5;40710:66;40726:49;40768:6;40726:49;:::i;:::-;40710:66;:::i;:::-;40701:75;;40795:6;40788:5;40781:21;40829:4;40822:5;40818:16;40863:3;40854:6;40849:3;40845:16;40842:25;40839:112;;;40870:79;;:::i;:::-;40839:112;40956:52;41001:6;40996:3;40991;40956:52;:::i;:::-;40695:315;40600:410;;;;;:::o;41022:339::-;41089:5;41134:3;41127:4;41119:6;41115:17;41111:27;41101:122;;41142:79;;:::i;:::-;41101:122;41248:6;41242:13;41269:90;41355:3;41347:6;41340:4;41332:6;41328:17;41269:90;:::i;:::-;41260:99;;41095:266;41022:339;;;;:::o;41363:496::-;41443:6;41488:2;41476:9;41467:7;41463:23;41459:32;41456:119;;;41494:79;;:::i;:::-;41456:119;41627:1;41616:9;41612:17;41606:24;41653:18;41645:6;41642:30;41639:117;;;41675:79;;:::i;:::-;41639:117;41776:74;41842:7;41833:6;41822:9;41818:22;41776:74;:::i;:::-;41766:84;;41581:275;41363:496;;;;:::o;41861:77::-;41906:7;41931:5;41920:16;;41861:77;;;:::o;41940:146::-;41996:9;42025:59;42041:42;42050:32;42076:5;42050:32;:::i;:::-;42041:42;:::i;:::-;42025:59;:::i;:::-;42012:72;;41940:146;;;:::o;42088:135::-;42177:43;42214:5;42177:43;:::i;:::-;42172:3;42165:56;42088:135;;:::o;42225:328::-;42352:4;42386:2;42375:9;42371:18;42363:26;;42395:77;42469:1;42458:9;42454:17;42445:6;42395:77;:::i;:::-;42478:72;42546:2;42535:9;42531:18;42522:6;42478:72;:::i;:::-;42225:328;;;;;:::o;42555:77::-;42600:7;42625:5;42614:16;;42555:77;;;:::o;42634:146::-;42690:9;42719:59;42735:42;42744:32;42770:5;42744:32;:::i;:::-;42735:42;:::i;:::-;42719:59;:::i;:::-;42706:72;;42634:146;;;:::o;42782:135::-;42871:43;42908:5;42871:43;:::i;:::-;42866:3;42859:56;42782:135;;:::o;42919:328::-;43046:4;43080:2;43069:9;43065:18;43057:26;;43089:77;43163:1;43152:9;43148:17;43139:6;43089:77;:::i;:::-;43172:72;43240:2;43229:9;43225:18;43216:6;43172:72;:::i;:::-;42919:328;;;;;:::o;43249:77::-;43294:7;43319:5;43308:16;;43249:77;;;:::o;43328:146::-;43384:9;43413:59;43429:42;43438:32;43464:5;43438:32;:::i;:::-;43429:42;:::i;:::-;43413:59;:::i;:::-;43400:72;;43328:146;;;:::o;43476:135::-;43565:43;43602:5;43565:43;:::i;:::-;43560:3;43553:56;43476:135;;:::o;43613:328::-;43740:4;43774:2;43763:9;43759:18;43751:26;;43783:77;43857:1;43846:9;43842:17;43833:6;43783:77;:::i;:::-;43866:72;43934:2;43923:9;43919:18;43910:6;43866:72;:::i;:::-;43613:328;;;;;:::o;43943:400::-;44079:66;44075:1;44067:6;44063:14;44056:90;44176:66;44171:2;44163:6;44159:15;44152:91;44273:66;44268:2;44260:6;44256:15;44249:91;43943:400;:::o;44345:386::-;44505:3;44522:85;44604:2;44599:3;44522:85;:::i;:::-;44515:92;;44612:93;44701:3;44612:93;:::i;:::-;44726:2;44721:3;44717:12;44710:19;;44345:386;;;:::o;44733:148::-;44869:8;44865:1;44857:6;44853:14;44846:32;44733:148;:::o;44883:384::-;45043:3;45060:84;45142:1;45137:3;45060:84;:::i;:::-;45053:91;;45149:93;45238:3;45149:93;:::i;:::-;45263:1;45258:3;45254:11;45247:18;;44883:384;;;:::o;45269:1255::-;45747:3;45765:148;45909:3;45765:148;:::i;:::-;45758:155;;45926:95;46017:3;46008:6;45926:95;:::i;:::-;45919:102;;46034:95;46125:3;46116:6;46034:95;:::i;:::-;46027:102;;46142:95;46233:3;46224:6;46142:95;:::i;:::-;46135:102;;46250:95;46341:3;46332:6;46250:95;:::i;:::-;46243:102;;46358:148;46502:3;46358:148;:::i;:::-;46351:155;;46519:3;46512:10;;45269:1255;;;;;;;:::o;46526:143::-;46662:3;46658:1;46650:6;46646:14;46639:27;46526:143;:::o;46671:384::-;46831:3;46848:84;46930:1;46925:3;46848:84;:::i;:::-;46841:91;;46937:93;47026:3;46937:93;:::i;:::-;47051:1;47046:3;47042:11;47035:18;;46671:384;;;:::o;47057:681::-;47338:3;47356:95;47447:3;47438:6;47356:95;:::i;:::-;47349:102;;47464:148;47608:3;47464:148;:::i;:::-;47457:155;;47625:95;47716:3;47707:6;47625:95;:::i;:::-;47618:102;;47733:3;47726:10;;47057:681;;;;;:::o;47740:155::-;47779:3;47798:24;47816:5;47798:24;:::i;:::-;47789:33;;47840:4;47833:5;47830:15;47827:41;;47848:18;;:::i;:::-;47827:41;47891:1;47884:5;47880:13;47873:20;;47740:155;;;:::o
Swarm Source
ipfs://2c0963c22cdf73981de98a45690851d2f22013786ccd482191c8f1d1cde8aac6
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.