Source Code
Overview
APE Balance
More Info
ContractCreator
TokenTracker
Latest 12 from a total of 12 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Mint Random Batc... | 16438061 | 18 days ago | IN | 0 APE | 0.00003962 | ||||
Mint Random Batc... | 16430642 | 19 days ago | IN | 0 APE | 0.00005915 | ||||
Mint Random Batc... | 16430528 | 19 days ago | IN | 0 APE | 0.00005921 | ||||
Mint Random Batc... | 16430524 | 19 days ago | IN | 0 APE | 0.00005975 | ||||
Mint Random Batc... | 16430523 | 19 days ago | IN | 0 APE | 0.00005816 | ||||
Mint Random Batc... | 16430522 | 19 days ago | IN | 0 APE | 0.00005883 | ||||
Mint Random Batc... | 16430521 | 19 days ago | IN | 0 APE | 0.00005796 | ||||
Mint Random Batc... | 16430520 | 19 days ago | IN | 0 APE | 0.00005895 | ||||
Mint Random Batc... | 16430517 | 19 days ago | IN | 0 APE | 0.00005935 | ||||
Mint Random Batc... | 16430516 | 19 days ago | IN | 0 APE | 0.00005849 | ||||
Mint Random Batc... | 16430515 | 19 days ago | IN | 0 APE | 0.00005995 | ||||
Mint Random Batc... | 16430513 | 19 days ago | IN | 0 APE | 0.00005907 |
Loading...
Loading
Contract Name:
OCSpikiesRandom
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity)
/** *Submitted for verification at curtis.apescan.io on 2025-03-09 */ // 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: 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 { // Inherit from ERC721Royalty ISpikiesDataSource public dataSource; uint256 public totalSupply; uint256 public constant MAX_SUPPLY = 5555; // Max 5,555 NFTs uint256 public constant MAX_BATCH_SIZE = 505; // Limit batch size to manage gas costs 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") ERC721Royalty() { dataSource = ISpikiesDataSource(_dataSource); _setDefaultRoyalty(royaltyReceiver, 690); // Set 6.9% royalty (690 basis points) } function mintRandom(address to) external 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; } function mintRandomBatch(address to, uint256 quantity) external returns (uint256[] memory) { require(quantity > 0 && quantity <= MAX_BATCH_SIZE, "Quantity must be between 1 and 20"); 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; // Fixed background 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",', '"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); } // Override required by ERC721Royalty to support both ERC721 and ERC2981 interfaces function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC721Royalty) returns (bool) { return super.supportsInterface(interfaceId); } }
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"},{"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":"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":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":"bytes32","name":"","type":"bytes32"}],"name":"usedCombinations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801562000010575f80fd5b50604051620046eb380380620046eb83398181016040528101906200003691906200033a565b6040518060400160405280600981526020017f4f435370696b69657300000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f4f435300000000000000000000000000000000000000000000000000000000008152508160029081620000b39190620005e3565b508060039081620000c59190620005e3565b5050508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506200011c816102b26200012460201b60201c565b50506200077e565b5f62000135620002cc60201b60201c565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156200019d5781816040517f6f483d090000000000000000000000000000000000000000000000000000000081526004016200019492919062000727565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000210575f6040517fb6d9900a00000000000000000000000000000000000000000000000000000000815260040162000207919062000763565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff168152505f80820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f612710905090565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6200030482620002d9565b9050919050565b6200031681620002f8565b811462000321575f80fd5b50565b5f8151905062000334816200030b565b92915050565b5f8060408385031215620003535762000352620002d5565b5b5f620003628582860162000324565b9250506020620003758582860162000324565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680620003fb57607f821691505b602082108103620004115762000410620003b6565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620004757fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000438565b62000481868362000438565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620004cb620004c5620004bf8462000499565b620004a2565b62000499565b9050919050565b5f819050919050565b620004e683620004ab565b620004fe620004f582620004d2565b84845462000444565b825550505050565b5f90565b6200051462000506565b62000521818484620004db565b505050565b5b8181101562000548576200053c5f826200050a565b60018101905062000527565b5050565b601f8211156200059757620005618162000417565b6200056c8462000429565b810160208510156200057c578190505b620005946200058b8562000429565b83018262000526565b50505b505050565b5f82821c905092915050565b5f620005b95f19846008026200059c565b1980831691505092915050565b5f620005d38383620005a8565b9150826002028217905092915050565b620005ee826200037f565b67ffffffffffffffff8111156200060a576200060962000389565b5b620006168254620003e3565b620006238282856200054c565b5f60209050601f83116001811462000659575f841562000644578287015190505b620006508582620005c6565b865550620006bf565b601f198416620006698662000417565b5f5b8281101562000692578489015182556001820191506020850194506020810190506200066b565b86831015620006b25784890151620006ae601f891682620005a8565b8355505b6001600288020188555050505b505050505050565b5f6bffffffffffffffffffffffff82169050919050565b5f620006fe620006f8620006f284620006c7565b620004a2565b62000499565b9050919050565b6200071081620006de565b82525050565b620007218162000499565b82525050565b5f6040820190506200073c5f83018562000705565b6200074b602083018462000716565b9392505050565b6200075d81620002f8565b82525050565b5f602082019050620007785f83018462000752565b92915050565b613f5f806200078c5f395ff3fe608060405234801561000f575f80fd5b506004361061014b575f3560e01c80636352211e116100c1578063c87b56dd1161007a578063c87b56dd146103c2578063cfdbf254146103f2578063d023f37e14610410578063d1cea4ec14610440578063e05c57bf14610470578063e985e9c5146104a25761014b565b80636352211e146102dc57806370a082311461030c5780637ecebe001461033c57806395d89b411461036c578063a22cb4651461038a578063b88d4fde146103a65761014b565b80631b076edc116101135780631b076edc1461020757806323b872dd146102255780632a55205a1461024157806332cb6b0c1461027257806342842e0e1461029057806349bc4aed146102ac5761014b565b806301ffc9a71461014f57806306fdde031461017f578063081812fc1461019d578063095ea7b3146101cd57806318160ddd146101e9575b5f80fd5b61016960048036038101906101649190612849565b6104d2565b604051610176919061288e565b60405180910390f35b6101876104e3565b6040516101949190612931565b60405180910390f35b6101b760048036038101906101b29190612984565b610573565b6040516101c491906129ee565b60405180910390f35b6101e760048036038101906101e29190612a31565b61058e565b005b6101f16105a4565b6040516101fe9190612a7e565b60405180910390f35b61020f6105aa565b60405161021c9190612af2565b60405180910390f35b61023f600480360381019061023a9190612b0b565b6105cf565b005b61025b60048036038101906102569190612b5b565b6106ce565b604051610269929190612b99565b60405180910390f35b61027a6107ee565b6040516102879190612a7e565b60405180910390f35b6102aa60048036038101906102a59190612b0b565b6107f4565b005b6102c660048036038101906102c19190612bf3565b610813565b6040516102d3919061288e565b60405180910390f35b6102f660048036038101906102f19190612984565b610830565b60405161030391906129ee565b60405180910390f35b61032660048036038101906103219190612c1e565b610841565b6040516103339190612a7e565b60405180910390f35b61035660048036038101906103519190612c1e565b6108f7565b6040516103639190612a7e565b60405180910390f35b61037461090c565b6040516103819190612931565b60405180910390f35b6103a4600480360381019061039f9190612c73565b61099c565b005b6103c060048036038101906103bb9190612ddd565b6109b2565b005b6103dc60048036038101906103d79190612984565b6109d7565b6040516103e99190612931565b60405180910390f35b6103fa610ac3565b6040516104079190612a7e565b60405180910390f35b61042a60048036038101906104259190612a31565b610ac9565b6040516104379190612f14565b60405180910390f35b61045a60048036038101906104559190612c1e565b610eec565b6040516104679190612a7e565b60405180910390f35b61048a60048036038101906104859190612984565b611226565b60405161049993929190612f34565b60405180910390f35b6104bc60048036038101906104b79190612f69565b61124c565b6040516104c9919061288e565b60405180910390f35b5f6104dc826112da565b9050919050565b6060600280546104f290612fd4565b80601f016020809104026020016040519081016040528092919081815260200182805461051e90612fd4565b80156105695780601f1061054057610100808354040283529160200191610569565b820191905f5260205f20905b81548152906001019060200180831161054c57829003601f168201915b5050505050905090565b5f61057d826112eb565b5061058782611371565b9050919050565b6105a0828261059b6113aa565b6113b1565b5050565b60095481565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361063f575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161063691906129ee565b60405180910390fd5b5f610652838361064d6113aa565b6113c3565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146106c8578382826040517f64283d7b0000000000000000000000000000000000000000000000000000000081526004016106bf93929190613004565b60405180910390fd5b50505050565b5f805f60015f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036107a0575f80015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505f800160149054906101000a90046bffffffffffffffffffffffff1690505b5f6107a96115ce565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff16886107d19190613066565b6107db91906130d4565b9050828195509550505050509250929050565b6115b381565b61080e83838360405180602001604052805f8152506109b2565b505050565b600b602052805f5260405f205f915054906101000a900460ff1681565b5f61083a826112eb565b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036108b2575f6040517f89c62b640000000000000000000000000000000000000000000000000000000081526004016108a991906129ee565b60405180910390fd5b60055f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b600c602052805f5260405f205f915090505481565b60606003805461091b90612fd4565b80601f016020809104026020016040519081016040528092919081815260200182805461094790612fd4565b80156109925780601f1061096957610100808354040283529160200191610992565b820191905f5260205f20905b81548152906001019060200180831161097557829003601f168201915b5050505050905090565b6109ae6109a76113aa565b83836115d7565b5050565b6109bd8484846105cf565b6109d16109c86113aa565b85858585611740565b50505050565b60606109e282610830565b505f600a5f8481526020019081526020015f206040518060600160405290815f82015481526020016001820154815260200160028201548152505090505f80825f015190505f836020015190505f846040015190505f610a44858585856118ec565b90505f610a5386868686611ba9565b90505f610a5f8a611e9e565b610a6884611ff6565b83604051602001610a7b9392919061336c565b6040516020818303038152906040529050610a9581611ff6565b604051602001610aa59190613433565b60405160208183030381529060405298505050505050505050919050565b6101f981565b60605f82118015610adc57506101f98211155b610b1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b12906134c4565b60405180910390fd5b6115b382600954610b2c91906134e2565b1115610b6d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6490613585565b60405180910390fd5b5f8267ffffffffffffffff811115610b8857610b87612cb9565b5b604051908082528060200260200182016040528015610bb65781602001602082028036833780820191505090505b5090505f5b83811015610ee157600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610c10906135a3565b91905055505f805f805f5b83158015610c295750600a85105b15610df6575f600143610c3c91906135ea565b4033600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205488604051602001610c9094939291906136a2565b604051602081830303815290604052805190602001205f1c90505f81604051602001610cbc9190613739565b604051602081830303815290604052805190602001205f1c90505f82604051602001610ce891906137a8565b604051602081830303815290604052805190602001205f1c90505f83604051602001610d149190613817565b604051602081830303815290604052805190602001205f1c9050608f83610d3b919061383c565b9650605682610d4a919061383c565b9550600d81610d59919061383c565b94505f878787604051602001610d719392919061386c565b604051602081830303815290604052805190602001209050600b5f8281526020019081526020015f205f9054906101000a900460ff16610ddd576001600b5f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555060019850610dec565b8980610de8906135a3565b9a50505b5050505050610c1b565b83610e36576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2d90613918565b60405180910390fd5b60095f815480929190610e48906135a3565b91905055505f6009549050604051806060016040528085815260200184815260200183815250600a5f8381526020019081526020015f205f820151815f01556020820151816001015560408201518160020155905050610ea88b82612023565b80888881518110610ebc57610ebb613936565b5b6020026020010181815250505050505050508080610ed9906135a3565b915050610bbb565b508091505092915050565b5f6115b360095410610f33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2a906139ad565b60405180910390fd5b600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610f80906135a3565b91905055505f805f805f5b83158015610f995750600a85105b15611166575f600143610fac91906135ea565b4033600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20548860405160200161100094939291906136a2565b604051602081830303815290604052805190602001205f1c90505f8160405160200161102c9190613739565b604051602081830303815290604052805190602001205f1c90505f8260405160200161105891906137a8565b604051602081830303815290604052805190602001205f1c90505f836040516020016110849190613817565b604051602081830303815290604052805190602001205f1c9050608f836110ab919061383c565b96506056826110ba919061383c565b9550600d816110c9919061383c565b94505f8787876040516020016110e19392919061386c565b604051602081830303815290604052805190602001209050600b5f8281526020019081526020015f205f9054906101000a900460ff1661114d576001600b5f8381526020019081526020015f205f6101000a81548160ff0219169083151502179055506001985061115c565b8980611158906135a3565b9a50505b5050505050610f8b565b836111a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119d90613918565b60405180910390fd5b60095f8154809291906111b8906135a3565b91905055505f6009549050604051806060016040528085815260200184815260200183815250600a5f8381526020019081526020015f205f820151815f015560208201518160010155604082015181600201559050506112188882612023565b809650505050505050919050565b600a602052805f5260405f205f91509050805f0154908060010154908060020154905083565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f6112e482612116565b9050919050565b5f806112f6836121f7565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361136857826040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161135f9190612a7e565b60405180910390fd5b80915050919050565b5f60065f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6113be8383836001612230565b505050565b5f806113ce846121f7565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461140f5761140e8184866123ef565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461149a5761144e5f855f80612230565b600160055f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161461151957600160055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460045f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b5f612710905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361164757816040517f5b08ba1800000000000000000000000000000000000000000000000000000000815260040161163e91906129ee565b60405180910390fd5b8060075f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611733919061288e565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b11156118e5578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b815260040161179e9493929190613a1d565b6020604051808303815f875af19250505080156117d957506040513d601f19601f820116820180604052508101906117d69190613a7b565b60015b61185a573d805f8114611807576040519150601f19603f3d011682016040523d82523d5f602084013e61180c565b606091505b505f81510361185257836040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161184991906129ee565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146118e357836040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016118da91906129ee565b60405180910390fd5b505b5050505050565b60605f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384855f886040518363ffffffff1660e01b815260040161194b929190613aeb565b5f60405180830381865afa158015611965573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061198d9190613bb0565b90505f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856005866040518363ffffffff1660e01b81526004016119ed929190613c30565b5f60405180830381865afa158015611a07573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611a2f9190613bb0565b90505f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856003896040518363ffffffff1660e01b8152600401611a8f929190613c90565b5f60405180830381865afa158015611aa9573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611ad19190613bb0565b90505f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856004896040518363ffffffff1660e01b8152600401611b31929190613cf0565b5f60405180830381865afa158015611b4b573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611b739190613bb0565b905083838383604051602001611b8c9493929190613df7565b604051602081830303815290604052945050505050949350505050565b60605f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b85f886040518363ffffffff1660e01b8152600401611c08929190613aeb565b5f60405180830381865afa158015611c22573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611c4a9190613bb0565b90508060085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86003886040518363ffffffff1660e01b8152600401611caa929190613c90565b5f60405180830381865afa158015611cc4573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611cec9190613bb0565b604051602001611cfd929190613e94565b60405160208183030381529060405290508060085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86004876040518363ffffffff1660e01b8152600401611d6c929190613cf0565b5f60405180830381865afa158015611d86573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611dae9190613bb0565b604051602001611dbf929190613e94565b60405160208183030381529060405290508060085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86005866040518363ffffffff1660e01b8152600401611e2e929190613c30565b5f60405180830381865afa158015611e48573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611e709190613bb0565b604051602001611e81929190613e94565b604051602081830303815290604052905080915050949350505050565b60605f8203611ee4576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611ff1565b5f8290505f5b5f8214611f13578080611efc906135a3565b915050600a82611f0c91906130d4565b9150611eea565b5f8167ffffffffffffffff811115611f2e57611f2d612cb9565b5b6040519080825280601f01601f191660200182016040528015611f605781602001600182028036833780820191505090505b5090505b5f8514611fea578180611f7690613ec2565b925050600a85611f86919061383c565b6030611f9291906134e2565b60f81b818381518110611fa857611fa7613936565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a85611fe391906130d4565b9450611f64565b8093505050505b919050565b606061201c82604051806060016040528060408152602001613eea6040913960016124b2565b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612093575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161208a91906129ee565b60405180910390fd5b5f61209f83835f6113c3565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612111575f6040517f73c6ac6e00000000000000000000000000000000000000000000000000000000815260040161210891906129ee565b60405180910390fd5b505050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806121e057507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806121f057506121ef82612641565b5b9050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061226857505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b1561239a575f612277846112eb565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156122e157508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156122f457506122f2818461124c565b155b1561233657826040517fa9fbf51f00000000000000000000000000000000000000000000000000000000815260040161232d91906129ee565b60405180910390fd5b811561239857838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360065f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b6123fa8383836126ba565b6124ad575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361246e57806040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016124659190612a7e565b60405180910390fd5b81816040517f177e802f0000000000000000000000000000000000000000000000000000000081526004016124a4929190612b99565b60405180910390fd5b505050565b60605f8451036124d25760405180602001604052805f815250905061263a565b5f826125035760036002865160046124ea9190613066565b6124f491906134e2565b6124fe91906130d4565b61252a565b60036002865161251391906134e2565b61251d91906130d4565b60046125299190613066565b5b90505f8167ffffffffffffffff81111561254757612546612cb9565b5b6040519080825280601f01601f1916602001820160405280156125795781602001600182028036833780820191505090505b509050600185016020820187885189016020810180515f82525b828410156125ee576003840193508351603f8160121c168701518653600186019550603f81600c1c168701518653600186019550603f8160061c168701518653600186019550603f8116870151865360018601955050612593565b808252891561262e5760038c51066001811461261157600281146126245761262c565b603d6001870353603d600287035361262c565b603d60018703535b505b50505050505080925050505b9392505050565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806126b357506126b28261277a565b5b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561277157508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806127325750612731848461124c565b5b8061277057508273ffffffffffffffffffffffffffffffffffffffff1661275883611371565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612828816127f4565b8114612832575f80fd5b50565b5f813590506128438161281f565b92915050565b5f6020828403121561285e5761285d6127ec565b5b5f61286b84828501612835565b91505092915050565b5f8115159050919050565b61288881612874565b82525050565b5f6020820190506128a15f83018461287f565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156128de5780820151818401526020810190506128c3565b5f8484015250505050565b5f601f19601f8301169050919050565b5f612903826128a7565b61290d81856128b1565b935061291d8185602086016128c1565b612926816128e9565b840191505092915050565b5f6020820190508181035f83015261294981846128f9565b905092915050565b5f819050919050565b61296381612951565b811461296d575f80fd5b50565b5f8135905061297e8161295a565b92915050565b5f60208284031215612999576129986127ec565b5b5f6129a684828501612970565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6129d8826129af565b9050919050565b6129e8816129ce565b82525050565b5f602082019050612a015f8301846129df565b92915050565b612a10816129ce565b8114612a1a575f80fd5b50565b5f81359050612a2b81612a07565b92915050565b5f8060408385031215612a4757612a466127ec565b5b5f612a5485828601612a1d565b9250506020612a6585828601612970565b9150509250929050565b612a7881612951565b82525050565b5f602082019050612a915f830184612a6f565b92915050565b5f819050919050565b5f612aba612ab5612ab0846129af565b612a97565b6129af565b9050919050565b5f612acb82612aa0565b9050919050565b5f612adc82612ac1565b9050919050565b612aec81612ad2565b82525050565b5f602082019050612b055f830184612ae3565b92915050565b5f805f60608486031215612b2257612b216127ec565b5b5f612b2f86828701612a1d565b9350506020612b4086828701612a1d565b9250506040612b5186828701612970565b9150509250925092565b5f8060408385031215612b7157612b706127ec565b5b5f612b7e85828601612970565b9250506020612b8f85828601612970565b9150509250929050565b5f604082019050612bac5f8301856129df565b612bb96020830184612a6f565b9392505050565b5f819050919050565b612bd281612bc0565b8114612bdc575f80fd5b50565b5f81359050612bed81612bc9565b92915050565b5f60208284031215612c0857612c076127ec565b5b5f612c1584828501612bdf565b91505092915050565b5f60208284031215612c3357612c326127ec565b5b5f612c4084828501612a1d565b91505092915050565b612c5281612874565b8114612c5c575f80fd5b50565b5f81359050612c6d81612c49565b92915050565b5f8060408385031215612c8957612c886127ec565b5b5f612c9685828601612a1d565b9250506020612ca785828601612c5f565b9150509250929050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612cef826128e9565b810181811067ffffffffffffffff82111715612d0e57612d0d612cb9565b5b80604052505050565b5f612d206127e3565b9050612d2c8282612ce6565b919050565b5f67ffffffffffffffff821115612d4b57612d4a612cb9565b5b612d54826128e9565b9050602081019050919050565b828183375f83830152505050565b5f612d81612d7c84612d31565b612d17565b905082815260208101848484011115612d9d57612d9c612cb5565b5b612da8848285612d61565b509392505050565b5f82601f830112612dc457612dc3612cb1565b5b8135612dd4848260208601612d6f565b91505092915050565b5f805f8060808587031215612df557612df46127ec565b5b5f612e0287828801612a1d565b9450506020612e1387828801612a1d565b9350506040612e2487828801612970565b925050606085013567ffffffffffffffff811115612e4557612e446127f0565b5b612e5187828801612db0565b91505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b612e8f81612951565b82525050565b5f612ea08383612e86565b60208301905092915050565b5f602082019050919050565b5f612ec282612e5d565b612ecc8185612e67565b9350612ed783612e77565b805f5b83811015612f07578151612eee8882612e95565b9750612ef983612eac565b925050600181019050612eda565b5085935050505092915050565b5f6020820190508181035f830152612f2c8184612eb8565b905092915050565b5f606082019050612f475f830186612a6f565b612f546020830185612a6f565b612f616040830184612a6f565b949350505050565b5f8060408385031215612f7f57612f7e6127ec565b5b5f612f8c85828601612a1d565b9250506020612f9d85828601612a1d565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612feb57607f821691505b602082108103612ffe57612ffd612fa7565b5b50919050565b5f6060820190506130175f8301866129df565b6130246020830185612a6f565b61303160408301846129df565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61307082612951565b915061307b83612951565b925082820261308981612951565b915082820484148315176130a05761309f613039565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6130de82612951565b91506130e983612951565b9250826130f9576130f86130a7565b5b828204905092915050565b5f81905092915050565b7f7b226e616d65223a225370696b792023000000000000000000000000000000005f82015250565b5f613142601083613104565b915061314d8261310e565b601082019050919050565b5f613162826128a7565b61316c8185613104565b935061317c8185602086016128c1565b80840191505092915050565b7f222c0000000000000000000000000000000000000000000000000000000000005f82015250565b5f6131bc600283613104565b91506131c782613188565b600282019050919050565b7f226465736372697074696f6e223a22416e206f6e2d636861696e20696d706c655f8201527f6d656e746174696f6e206f66205370696b696573204e4654206f6e204170654360208201527f6861696e222c0000000000000000000000000000000000000000000000000000604082015250565b5f613252604683613104565b915061325d826131d2565b604682019050919050565b7f22696d616765223a22646174613a696d6167652f7376672b786d6c3b626173655f8201527f36342c0000000000000000000000000000000000000000000000000000000000602082015250565b5f6132c2602383613104565b91506132cd82613268565b602382019050919050565b7f2261747472696275746573223a5b0000000000000000000000000000000000005f82015250565b5f61330c600e83613104565b9150613317826132d8565b600e82019050919050565b7f5d7d0000000000000000000000000000000000000000000000000000000000005f82015250565b5f613356600283613104565b915061336182613322565b600282019050919050565b5f61337682613136565b91506133828286613158565b915061338d826131b0565b915061339882613246565b91506133a3826132b6565b91506133af8285613158565b91506133ba826131b0565b91506133c582613300565b91506133d18284613158565b91506133dc8261334a565b9150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f61341d601d83613104565b9150613428826133e9565b601d82019050919050565b5f61343d82613411565b91506134498284613158565b915081905092915050565b7f5175616e74697479206d757374206265206265747765656e203120616e6420325f8201527f3000000000000000000000000000000000000000000000000000000000000000602082015250565b5f6134ae6021836128b1565b91506134b982613454565b604082019050919050565b5f6020820190508181035f8301526134db816134a2565b9050919050565b5f6134ec82612951565b91506134f783612951565b925082820190508082111561350f5761350e613039565b5b92915050565b7f4261746368206d696e7420776f756c6420657863656564206d617820737570705f8201527f6c79000000000000000000000000000000000000000000000000000000000000602082015250565b5f61356f6022836128b1565b915061357a82613515565b604082019050919050565b5f6020820190508181035f83015261359c81613563565b9050919050565b5f6135ad82612951565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135df576135de613039565b5b600182019050919050565b5f6135f482612951565b91506135ff83612951565b925082820390508181111561361757613616613039565b5b92915050565b5f819050919050565b61363761363282612bc0565b61361d565b82525050565b5f8160601b9050919050565b5f6136538261363d565b9050919050565b5f61366482613649565b9050919050565b61367c613677826129ce565b61365a565b82525050565b5f819050919050565b61369c61369782612951565b613682565b82525050565b5f6136ad8287613626565b6020820191506136bd828661366b565b6014820191506136cd828561368b565b6020820191506136dd828461368b565b60208201915081905095945050505050565b7f65796573000000000000000000000000000000000000000000000000000000005f82015250565b5f613723600483613104565b915061372e826136ef565b600482019050919050565b5f613744828461368b565b60208201915061375382613717565b915081905092915050565b7f68656164730000000000000000000000000000000000000000000000000000005f82015250565b5f613792600583613104565b915061379d8261375e565b600582019050919050565b5f6137b3828461368b565b6020820191506137c282613786565b915081905092915050565b7f6d6f7574687300000000000000000000000000000000000000000000000000005f82015250565b5f613801600683613104565b915061380c826137cd565b600682019050919050565b5f613822828461368b565b602082019150613831826137f5565b915081905092915050565b5f61384682612951565b915061385183612951565b925082613861576138606130a7565b5b828206905092915050565b5f613877828661368b565b602082019150613887828561368b565b602082019150613897828461368b565b602082019150819050949350505050565b7f4e6f20756e6971756520636f6d62696e6174696f6e20666f756e6420616674655f8201527f7220313020617474656d70747300000000000000000000000000000000000000602082015250565b5f613902602d836128b1565b915061390d826138a8565b604082019050919050565b5f6020820190508181035f83015261392f816138f6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f6139976012836128b1565b91506139a282613963565b602082019050919050565b5f6020820190508181035f8301526139c48161398b565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f6139ef826139cb565b6139f981856139d5565b9350613a098185602086016128c1565b613a12816128e9565b840191505092915050565b5f608082019050613a305f8301876129df565b613a3d60208301866129df565b613a4a6040830185612a6f565b8181036060830152613a5c81846139e5565b905095945050505050565b5f81519050613a758161281f565b92915050565b5f60208284031215613a9057613a8f6127ec565b5b5f613a9d84828501613a67565b91505092915050565b5f819050919050565b5f60ff82169050919050565b5f613ad5613ad0613acb84613aa6565b612a97565b613aaf565b9050919050565b613ae581613abb565b82525050565b5f604082019050613afe5f830185613adc565b613b0b6020830184612a6f565b9392505050565b5f67ffffffffffffffff821115613b2c57613b2b612cb9565b5b613b35826128e9565b9050602081019050919050565b5f613b54613b4f84613b12565b612d17565b905082815260208101848484011115613b7057613b6f612cb5565b5b613b7b8482856128c1565b509392505050565b5f82601f830112613b9757613b96612cb1565b5b8151613ba7848260208601613b42565b91505092915050565b5f60208284031215613bc557613bc46127ec565b5b5f82015167ffffffffffffffff811115613be257613be16127f0565b5b613bee84828501613b83565b91505092915050565b5f819050919050565b5f613c1a613c15613c1084613bf7565b612a97565b613aaf565b9050919050565b613c2a81613c00565b82525050565b5f604082019050613c435f830185613c21565b613c506020830184612a6f565b9392505050565b5f819050919050565b5f613c7a613c75613c7084613c57565b612a97565b613aaf565b9050919050565b613c8a81613c60565b82525050565b5f604082019050613ca35f830185613c81565b613cb06020830184612a6f565b9392505050565b5f819050919050565b5f613cda613cd5613cd084613cb7565b612a97565b613aaf565b9050919050565b613cea81613cc0565b82525050565b5f604082019050613d035f830185613ce1565b613d106020830184612a6f565b9392505050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f32305f8201527f30302f737667222077696474683d2235313222206865696768743d223531322260208201527f2076696577426f783d223020302035313220353132223e000000000000000000604082015250565b5f613d97605783613104565b9150613da282613d17565b605782019050919050565b7f3c2f7376673e00000000000000000000000000000000000000000000000000005f82015250565b5f613de1600683613104565b9150613dec82613dad565b600682019050919050565b5f613e0182613d8b565b9150613e0d8287613158565b9150613e198286613158565b9150613e258285613158565b9150613e318284613158565b9150613e3c82613dd5565b915081905095945050505050565b7f2c000000000000000000000000000000000000000000000000000000000000005f82015250565b5f613e7e600183613104565b9150613e8982613e4a565b600182019050919050565b5f613e9f8285613158565b9150613eaa82613e72565b9150613eb68284613158565b91508190509392505050565b5f613ecc82612951565b91505f8203613ede57613edd613039565b5b60018203905091905056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220ff5ccad0d63612ff77ea26061303a21a2339f9400969477e5ffa3561607bcde064736f6c6343000814003300000000000000000000000059681edb59522513f57631ed555fec3189b6bdef000000000000000000000000a3097f1df53cc1d55e0ba7f2299811fe4940e24d
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061014b575f3560e01c80636352211e116100c1578063c87b56dd1161007a578063c87b56dd146103c2578063cfdbf254146103f2578063d023f37e14610410578063d1cea4ec14610440578063e05c57bf14610470578063e985e9c5146104a25761014b565b80636352211e146102dc57806370a082311461030c5780637ecebe001461033c57806395d89b411461036c578063a22cb4651461038a578063b88d4fde146103a65761014b565b80631b076edc116101135780631b076edc1461020757806323b872dd146102255780632a55205a1461024157806332cb6b0c1461027257806342842e0e1461029057806349bc4aed146102ac5761014b565b806301ffc9a71461014f57806306fdde031461017f578063081812fc1461019d578063095ea7b3146101cd57806318160ddd146101e9575b5f80fd5b61016960048036038101906101649190612849565b6104d2565b604051610176919061288e565b60405180910390f35b6101876104e3565b6040516101949190612931565b60405180910390f35b6101b760048036038101906101b29190612984565b610573565b6040516101c491906129ee565b60405180910390f35b6101e760048036038101906101e29190612a31565b61058e565b005b6101f16105a4565b6040516101fe9190612a7e565b60405180910390f35b61020f6105aa565b60405161021c9190612af2565b60405180910390f35b61023f600480360381019061023a9190612b0b565b6105cf565b005b61025b60048036038101906102569190612b5b565b6106ce565b604051610269929190612b99565b60405180910390f35b61027a6107ee565b6040516102879190612a7e565b60405180910390f35b6102aa60048036038101906102a59190612b0b565b6107f4565b005b6102c660048036038101906102c19190612bf3565b610813565b6040516102d3919061288e565b60405180910390f35b6102f660048036038101906102f19190612984565b610830565b60405161030391906129ee565b60405180910390f35b61032660048036038101906103219190612c1e565b610841565b6040516103339190612a7e565b60405180910390f35b61035660048036038101906103519190612c1e565b6108f7565b6040516103639190612a7e565b60405180910390f35b61037461090c565b6040516103819190612931565b60405180910390f35b6103a4600480360381019061039f9190612c73565b61099c565b005b6103c060048036038101906103bb9190612ddd565b6109b2565b005b6103dc60048036038101906103d79190612984565b6109d7565b6040516103e99190612931565b60405180910390f35b6103fa610ac3565b6040516104079190612a7e565b60405180910390f35b61042a60048036038101906104259190612a31565b610ac9565b6040516104379190612f14565b60405180910390f35b61045a60048036038101906104559190612c1e565b610eec565b6040516104679190612a7e565b60405180910390f35b61048a60048036038101906104859190612984565b611226565b60405161049993929190612f34565b60405180910390f35b6104bc60048036038101906104b79190612f69565b61124c565b6040516104c9919061288e565b60405180910390f35b5f6104dc826112da565b9050919050565b6060600280546104f290612fd4565b80601f016020809104026020016040519081016040528092919081815260200182805461051e90612fd4565b80156105695780601f1061054057610100808354040283529160200191610569565b820191905f5260205f20905b81548152906001019060200180831161054c57829003601f168201915b5050505050905090565b5f61057d826112eb565b5061058782611371565b9050919050565b6105a0828261059b6113aa565b6113b1565b5050565b60095481565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361063f575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161063691906129ee565b60405180910390fd5b5f610652838361064d6113aa565b6113c3565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146106c8578382826040517f64283d7b0000000000000000000000000000000000000000000000000000000081526004016106bf93929190613004565b60405180910390fd5b50505050565b5f805f60015f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036107a0575f80015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505f800160149054906101000a90046bffffffffffffffffffffffff1690505b5f6107a96115ce565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff16886107d19190613066565b6107db91906130d4565b9050828195509550505050509250929050565b6115b381565b61080e83838360405180602001604052805f8152506109b2565b505050565b600b602052805f5260405f205f915054906101000a900460ff1681565b5f61083a826112eb565b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036108b2575f6040517f89c62b640000000000000000000000000000000000000000000000000000000081526004016108a991906129ee565b60405180910390fd5b60055f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b600c602052805f5260405f205f915090505481565b60606003805461091b90612fd4565b80601f016020809104026020016040519081016040528092919081815260200182805461094790612fd4565b80156109925780601f1061096957610100808354040283529160200191610992565b820191905f5260205f20905b81548152906001019060200180831161097557829003601f168201915b5050505050905090565b6109ae6109a76113aa565b83836115d7565b5050565b6109bd8484846105cf565b6109d16109c86113aa565b85858585611740565b50505050565b60606109e282610830565b505f600a5f8481526020019081526020015f206040518060600160405290815f82015481526020016001820154815260200160028201548152505090505f80825f015190505f836020015190505f846040015190505f610a44858585856118ec565b90505f610a5386868686611ba9565b90505f610a5f8a611e9e565b610a6884611ff6565b83604051602001610a7b9392919061336c565b6040516020818303038152906040529050610a9581611ff6565b604051602001610aa59190613433565b60405160208183030381529060405298505050505050505050919050565b6101f981565b60605f82118015610adc57506101f98211155b610b1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b12906134c4565b60405180910390fd5b6115b382600954610b2c91906134e2565b1115610b6d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b6490613585565b60405180910390fd5b5f8267ffffffffffffffff811115610b8857610b87612cb9565b5b604051908082528060200260200182016040528015610bb65781602001602082028036833780820191505090505b5090505f5b83811015610ee157600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610c10906135a3565b91905055505f805f805f5b83158015610c295750600a85105b15610df6575f600143610c3c91906135ea565b4033600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205488604051602001610c9094939291906136a2565b604051602081830303815290604052805190602001205f1c90505f81604051602001610cbc9190613739565b604051602081830303815290604052805190602001205f1c90505f82604051602001610ce891906137a8565b604051602081830303815290604052805190602001205f1c90505f83604051602001610d149190613817565b604051602081830303815290604052805190602001205f1c9050608f83610d3b919061383c565b9650605682610d4a919061383c565b9550600d81610d59919061383c565b94505f878787604051602001610d719392919061386c565b604051602081830303815290604052805190602001209050600b5f8281526020019081526020015f205f9054906101000a900460ff16610ddd576001600b5f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555060019850610dec565b8980610de8906135a3565b9a50505b5050505050610c1b565b83610e36576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2d90613918565b60405180910390fd5b60095f815480929190610e48906135a3565b91905055505f6009549050604051806060016040528085815260200184815260200183815250600a5f8381526020019081526020015f205f820151815f01556020820151816001015560408201518160020155905050610ea88b82612023565b80888881518110610ebc57610ebb613936565b5b6020026020010181815250505050505050508080610ed9906135a3565b915050610bbb565b508091505092915050565b5f6115b360095410610f33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2a906139ad565b60405180910390fd5b600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610f80906135a3565b91905055505f805f805f5b83158015610f995750600a85105b15611166575f600143610fac91906135ea565b4033600c5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20548860405160200161100094939291906136a2565b604051602081830303815290604052805190602001205f1c90505f8160405160200161102c9190613739565b604051602081830303815290604052805190602001205f1c90505f8260405160200161105891906137a8565b604051602081830303815290604052805190602001205f1c90505f836040516020016110849190613817565b604051602081830303815290604052805190602001205f1c9050608f836110ab919061383c565b96506056826110ba919061383c565b9550600d816110c9919061383c565b94505f8787876040516020016110e19392919061386c565b604051602081830303815290604052805190602001209050600b5f8281526020019081526020015f205f9054906101000a900460ff1661114d576001600b5f8381526020019081526020015f205f6101000a81548160ff0219169083151502179055506001985061115c565b8980611158906135a3565b9a50505b5050505050610f8b565b836111a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161119d90613918565b60405180910390fd5b60095f8154809291906111b8906135a3565b91905055505f6009549050604051806060016040528085815260200184815260200183815250600a5f8381526020019081526020015f205f820151815f015560208201518160010155604082015181600201559050506112188882612023565b809650505050505050919050565b600a602052805f5260405f205f91509050805f0154908060010154908060020154905083565b5f60075f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f6112e482612116565b9050919050565b5f806112f6836121f7565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361136857826040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161135f9190612a7e565b60405180910390fd5b80915050919050565b5f60065f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6113be8383836001612230565b505050565b5f806113ce846121f7565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461140f5761140e8184866123ef565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461149a5761144e5f855f80612230565b600160055f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161461151957600160055f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460045f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b5f612710905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361164757816040517f5b08ba1800000000000000000000000000000000000000000000000000000000815260040161163e91906129ee565b60405180910390fd5b8060075f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611733919061288e565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b11156118e5578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b815260040161179e9493929190613a1d565b6020604051808303815f875af19250505080156117d957506040513d601f19601f820116820180604052508101906117d69190613a7b565b60015b61185a573d805f8114611807576040519150601f19603f3d011682016040523d82523d5f602084013e61180c565b606091505b505f81510361185257836040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161184991906129ee565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146118e357836040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016118da91906129ee565b60405180910390fd5b505b5050505050565b60605f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384855f886040518363ffffffff1660e01b815260040161194b929190613aeb565b5f60405180830381865afa158015611965573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061198d9190613bb0565b90505f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856005866040518363ffffffff1660e01b81526004016119ed929190613c30565b5f60405180830381865afa158015611a07573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611a2f9190613bb0565b90505f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856003896040518363ffffffff1660e01b8152600401611a8f929190613c90565b5f60405180830381865afa158015611aa9573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611ad19190613bb0565b90505f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634ae384856004896040518363ffffffff1660e01b8152600401611b31929190613cf0565b5f60405180830381865afa158015611b4b573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611b739190613bb0565b905083838383604051602001611b8c9493929190613df7565b604051602081830303815290604052945050505050949350505050565b60605f60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b85f886040518363ffffffff1660e01b8152600401611c08929190613aeb565b5f60405180830381865afa158015611c22573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611c4a9190613bb0565b90508060085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86003886040518363ffffffff1660e01b8152600401611caa929190613c90565b5f60405180830381865afa158015611cc4573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611cec9190613bb0565b604051602001611cfd929190613e94565b60405160208183030381529060405290508060085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86004876040518363ffffffff1660e01b8152600401611d6c929190613cf0565b5f60405180830381865afa158015611d86573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611dae9190613bb0565b604051602001611dbf929190613e94565b60405160208183030381529060405290508060085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6284b86005866040518363ffffffff1660e01b8152600401611e2e929190613c30565b5f60405180830381865afa158015611e48573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611e709190613bb0565b604051602001611e81929190613e94565b604051602081830303815290604052905080915050949350505050565b60605f8203611ee4576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611ff1565b5f8290505f5b5f8214611f13578080611efc906135a3565b915050600a82611f0c91906130d4565b9150611eea565b5f8167ffffffffffffffff811115611f2e57611f2d612cb9565b5b6040519080825280601f01601f191660200182016040528015611f605781602001600182028036833780820191505090505b5090505b5f8514611fea578180611f7690613ec2565b925050600a85611f86919061383c565b6030611f9291906134e2565b60f81b818381518110611fa857611fa7613936565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a85611fe391906130d4565b9450611f64565b8093505050505b919050565b606061201c82604051806060016040528060408152602001613eea6040913960016124b2565b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612093575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161208a91906129ee565b60405180910390fd5b5f61209f83835f6113c3565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612111575f6040517f73c6ac6e00000000000000000000000000000000000000000000000000000000815260040161210891906129ee565b60405180910390fd5b505050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806121e057507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806121f057506121ef82612641565b5b9050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061226857505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b1561239a575f612277846112eb565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156122e157508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156122f457506122f2818461124c565b155b1561233657826040517fa9fbf51f00000000000000000000000000000000000000000000000000000000815260040161232d91906129ee565b60405180910390fd5b811561239857838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360065f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b6123fa8383836126ba565b6124ad575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361246e57806040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016124659190612a7e565b60405180910390fd5b81816040517f177e802f0000000000000000000000000000000000000000000000000000000081526004016124a4929190612b99565b60405180910390fd5b505050565b60605f8451036124d25760405180602001604052805f815250905061263a565b5f826125035760036002865160046124ea9190613066565b6124f491906134e2565b6124fe91906130d4565b61252a565b60036002865161251391906134e2565b61251d91906130d4565b60046125299190613066565b5b90505f8167ffffffffffffffff81111561254757612546612cb9565b5b6040519080825280601f01601f1916602001820160405280156125795781602001600182028036833780820191505090505b509050600185016020820187885189016020810180515f82525b828410156125ee576003840193508351603f8160121c168701518653600186019550603f81600c1c168701518653600186019550603f8160061c168701518653600186019550603f8116870151865360018601955050612593565b808252891561262e5760038c51066001811461261157600281146126245761262c565b603d6001870353603d600287035361262c565b603d60018703535b505b50505050505080925050505b9392505050565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806126b357506126b28261277a565b5b9050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561277157508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806127325750612731848461124c565b5b8061277057508273ffffffffffffffffffffffffffffffffffffffff1661275883611371565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612828816127f4565b8114612832575f80fd5b50565b5f813590506128438161281f565b92915050565b5f6020828403121561285e5761285d6127ec565b5b5f61286b84828501612835565b91505092915050565b5f8115159050919050565b61288881612874565b82525050565b5f6020820190506128a15f83018461287f565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156128de5780820151818401526020810190506128c3565b5f8484015250505050565b5f601f19601f8301169050919050565b5f612903826128a7565b61290d81856128b1565b935061291d8185602086016128c1565b612926816128e9565b840191505092915050565b5f6020820190508181035f83015261294981846128f9565b905092915050565b5f819050919050565b61296381612951565b811461296d575f80fd5b50565b5f8135905061297e8161295a565b92915050565b5f60208284031215612999576129986127ec565b5b5f6129a684828501612970565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6129d8826129af565b9050919050565b6129e8816129ce565b82525050565b5f602082019050612a015f8301846129df565b92915050565b612a10816129ce565b8114612a1a575f80fd5b50565b5f81359050612a2b81612a07565b92915050565b5f8060408385031215612a4757612a466127ec565b5b5f612a5485828601612a1d565b9250506020612a6585828601612970565b9150509250929050565b612a7881612951565b82525050565b5f602082019050612a915f830184612a6f565b92915050565b5f819050919050565b5f612aba612ab5612ab0846129af565b612a97565b6129af565b9050919050565b5f612acb82612aa0565b9050919050565b5f612adc82612ac1565b9050919050565b612aec81612ad2565b82525050565b5f602082019050612b055f830184612ae3565b92915050565b5f805f60608486031215612b2257612b216127ec565b5b5f612b2f86828701612a1d565b9350506020612b4086828701612a1d565b9250506040612b5186828701612970565b9150509250925092565b5f8060408385031215612b7157612b706127ec565b5b5f612b7e85828601612970565b9250506020612b8f85828601612970565b9150509250929050565b5f604082019050612bac5f8301856129df565b612bb96020830184612a6f565b9392505050565b5f819050919050565b612bd281612bc0565b8114612bdc575f80fd5b50565b5f81359050612bed81612bc9565b92915050565b5f60208284031215612c0857612c076127ec565b5b5f612c1584828501612bdf565b91505092915050565b5f60208284031215612c3357612c326127ec565b5b5f612c4084828501612a1d565b91505092915050565b612c5281612874565b8114612c5c575f80fd5b50565b5f81359050612c6d81612c49565b92915050565b5f8060408385031215612c8957612c886127ec565b5b5f612c9685828601612a1d565b9250506020612ca785828601612c5f565b9150509250929050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612cef826128e9565b810181811067ffffffffffffffff82111715612d0e57612d0d612cb9565b5b80604052505050565b5f612d206127e3565b9050612d2c8282612ce6565b919050565b5f67ffffffffffffffff821115612d4b57612d4a612cb9565b5b612d54826128e9565b9050602081019050919050565b828183375f83830152505050565b5f612d81612d7c84612d31565b612d17565b905082815260208101848484011115612d9d57612d9c612cb5565b5b612da8848285612d61565b509392505050565b5f82601f830112612dc457612dc3612cb1565b5b8135612dd4848260208601612d6f565b91505092915050565b5f805f8060808587031215612df557612df46127ec565b5b5f612e0287828801612a1d565b9450506020612e1387828801612a1d565b9350506040612e2487828801612970565b925050606085013567ffffffffffffffff811115612e4557612e446127f0565b5b612e5187828801612db0565b91505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b612e8f81612951565b82525050565b5f612ea08383612e86565b60208301905092915050565b5f602082019050919050565b5f612ec282612e5d565b612ecc8185612e67565b9350612ed783612e77565b805f5b83811015612f07578151612eee8882612e95565b9750612ef983612eac565b925050600181019050612eda565b5085935050505092915050565b5f6020820190508181035f830152612f2c8184612eb8565b905092915050565b5f606082019050612f475f830186612a6f565b612f546020830185612a6f565b612f616040830184612a6f565b949350505050565b5f8060408385031215612f7f57612f7e6127ec565b5b5f612f8c85828601612a1d565b9250506020612f9d85828601612a1d565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612feb57607f821691505b602082108103612ffe57612ffd612fa7565b5b50919050565b5f6060820190506130175f8301866129df565b6130246020830185612a6f565b61303160408301846129df565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61307082612951565b915061307b83612951565b925082820261308981612951565b915082820484148315176130a05761309f613039565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6130de82612951565b91506130e983612951565b9250826130f9576130f86130a7565b5b828204905092915050565b5f81905092915050565b7f7b226e616d65223a225370696b792023000000000000000000000000000000005f82015250565b5f613142601083613104565b915061314d8261310e565b601082019050919050565b5f613162826128a7565b61316c8185613104565b935061317c8185602086016128c1565b80840191505092915050565b7f222c0000000000000000000000000000000000000000000000000000000000005f82015250565b5f6131bc600283613104565b91506131c782613188565b600282019050919050565b7f226465736372697074696f6e223a22416e206f6e2d636861696e20696d706c655f8201527f6d656e746174696f6e206f66205370696b696573204e4654206f6e204170654360208201527f6861696e222c0000000000000000000000000000000000000000000000000000604082015250565b5f613252604683613104565b915061325d826131d2565b604682019050919050565b7f22696d616765223a22646174613a696d6167652f7376672b786d6c3b626173655f8201527f36342c0000000000000000000000000000000000000000000000000000000000602082015250565b5f6132c2602383613104565b91506132cd82613268565b602382019050919050565b7f2261747472696275746573223a5b0000000000000000000000000000000000005f82015250565b5f61330c600e83613104565b9150613317826132d8565b600e82019050919050565b7f5d7d0000000000000000000000000000000000000000000000000000000000005f82015250565b5f613356600283613104565b915061336182613322565b600282019050919050565b5f61337682613136565b91506133828286613158565b915061338d826131b0565b915061339882613246565b91506133a3826132b6565b91506133af8285613158565b91506133ba826131b0565b91506133c582613300565b91506133d18284613158565b91506133dc8261334a565b9150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f61341d601d83613104565b9150613428826133e9565b601d82019050919050565b5f61343d82613411565b91506134498284613158565b915081905092915050565b7f5175616e74697479206d757374206265206265747765656e203120616e6420325f8201527f3000000000000000000000000000000000000000000000000000000000000000602082015250565b5f6134ae6021836128b1565b91506134b982613454565b604082019050919050565b5f6020820190508181035f8301526134db816134a2565b9050919050565b5f6134ec82612951565b91506134f783612951565b925082820190508082111561350f5761350e613039565b5b92915050565b7f4261746368206d696e7420776f756c6420657863656564206d617820737570705f8201527f6c79000000000000000000000000000000000000000000000000000000000000602082015250565b5f61356f6022836128b1565b915061357a82613515565b604082019050919050565b5f6020820190508181035f83015261359c81613563565b9050919050565b5f6135ad82612951565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135df576135de613039565b5b600182019050919050565b5f6135f482612951565b91506135ff83612951565b925082820390508181111561361757613616613039565b5b92915050565b5f819050919050565b61363761363282612bc0565b61361d565b82525050565b5f8160601b9050919050565b5f6136538261363d565b9050919050565b5f61366482613649565b9050919050565b61367c613677826129ce565b61365a565b82525050565b5f819050919050565b61369c61369782612951565b613682565b82525050565b5f6136ad8287613626565b6020820191506136bd828661366b565b6014820191506136cd828561368b565b6020820191506136dd828461368b565b60208201915081905095945050505050565b7f65796573000000000000000000000000000000000000000000000000000000005f82015250565b5f613723600483613104565b915061372e826136ef565b600482019050919050565b5f613744828461368b565b60208201915061375382613717565b915081905092915050565b7f68656164730000000000000000000000000000000000000000000000000000005f82015250565b5f613792600583613104565b915061379d8261375e565b600582019050919050565b5f6137b3828461368b565b6020820191506137c282613786565b915081905092915050565b7f6d6f7574687300000000000000000000000000000000000000000000000000005f82015250565b5f613801600683613104565b915061380c826137cd565b600682019050919050565b5f613822828461368b565b602082019150613831826137f5565b915081905092915050565b5f61384682612951565b915061385183612951565b925082613861576138606130a7565b5b828206905092915050565b5f613877828661368b565b602082019150613887828561368b565b602082019150613897828461368b565b602082019150819050949350505050565b7f4e6f20756e6971756520636f6d62696e6174696f6e20666f756e6420616674655f8201527f7220313020617474656d70747300000000000000000000000000000000000000602082015250565b5f613902602d836128b1565b915061390d826138a8565b604082019050919050565b5f6020820190508181035f83015261392f816138f6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f6139976012836128b1565b91506139a282613963565b602082019050919050565b5f6020820190508181035f8301526139c48161398b565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f6139ef826139cb565b6139f981856139d5565b9350613a098185602086016128c1565b613a12816128e9565b840191505092915050565b5f608082019050613a305f8301876129df565b613a3d60208301866129df565b613a4a6040830185612a6f565b8181036060830152613a5c81846139e5565b905095945050505050565b5f81519050613a758161281f565b92915050565b5f60208284031215613a9057613a8f6127ec565b5b5f613a9d84828501613a67565b91505092915050565b5f819050919050565b5f60ff82169050919050565b5f613ad5613ad0613acb84613aa6565b612a97565b613aaf565b9050919050565b613ae581613abb565b82525050565b5f604082019050613afe5f830185613adc565b613b0b6020830184612a6f565b9392505050565b5f67ffffffffffffffff821115613b2c57613b2b612cb9565b5b613b35826128e9565b9050602081019050919050565b5f613b54613b4f84613b12565b612d17565b905082815260208101848484011115613b7057613b6f612cb5565b5b613b7b8482856128c1565b509392505050565b5f82601f830112613b9757613b96612cb1565b5b8151613ba7848260208601613b42565b91505092915050565b5f60208284031215613bc557613bc46127ec565b5b5f82015167ffffffffffffffff811115613be257613be16127f0565b5b613bee84828501613b83565b91505092915050565b5f819050919050565b5f613c1a613c15613c1084613bf7565b612a97565b613aaf565b9050919050565b613c2a81613c00565b82525050565b5f604082019050613c435f830185613c21565b613c506020830184612a6f565b9392505050565b5f819050919050565b5f613c7a613c75613c7084613c57565b612a97565b613aaf565b9050919050565b613c8a81613c60565b82525050565b5f604082019050613ca35f830185613c81565b613cb06020830184612a6f565b9392505050565b5f819050919050565b5f613cda613cd5613cd084613cb7565b612a97565b613aaf565b9050919050565b613cea81613cc0565b82525050565b5f604082019050613d035f830185613ce1565b613d106020830184612a6f565b9392505050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f32305f8201527f30302f737667222077696474683d2235313222206865696768743d223531322260208201527f2076696577426f783d223020302035313220353132223e000000000000000000604082015250565b5f613d97605783613104565b9150613da282613d17565b605782019050919050565b7f3c2f7376673e00000000000000000000000000000000000000000000000000005f82015250565b5f613de1600683613104565b9150613dec82613dad565b600682019050919050565b5f613e0182613d8b565b9150613e0d8287613158565b9150613e198286613158565b9150613e258285613158565b9150613e318284613158565b9150613e3c82613dd5565b915081905095945050505050565b7f2c000000000000000000000000000000000000000000000000000000000000005f82015250565b5f613e7e600183613104565b9150613e8982613e4a565b600182019050919050565b5f613e9f8285613158565b9150613eaa82613e72565b9150613eb68284613158565b91508190509392505050565b5f613ecc82612951565b91505f8203613ede57613edd613039565b5b60018203905091905056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220ff5ccad0d63612ff77ea26061303a21a2339f9400969477e5ffa3561607bcde064736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000059681edb59522513f57631ed555fec3189b6bdef000000000000000000000000a3097f1df53cc1d55e0ba7f2299811fe4940e24d
-----Decoded View---------------
Arg [0] : _dataSource (address): 0x59681edb59522513f57631eD555fEc3189B6bdef
Arg [1] : royaltyReceiver (address): 0xA3097F1dF53cc1d55E0Ba7F2299811fE4940e24D
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000059681edb59522513f57631ed555fec3189b6bdef
Arg [1] : 000000000000000000000000a3097f1df53cc1d55e0ba7f2299811fe4940e24d
Deployed Bytecode Sourcemap
135460:7508:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;142733:232;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;107481:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108653:158;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108472:115;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;135590:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;135547:36;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109322:588;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;130769:673;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;135623:41;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109981:134;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;135936:48;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;107294:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;107019:213;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;135991:41;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;107641:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108883:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;110186:236;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;139730:1038;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;135689:44;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;137813:1909;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;136329:1476;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;135884:45;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;109100:155;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;142733:232;142891:4;142921:36;142945:11;142921:23;:36::i;:::-;142914:43;;142733:232;;;:::o;107481:91::-;107526:13;107559:5;107552:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107481:91;:::o;108653:158::-;108720:7;108740:22;108754:7;108740:13;:22::i;:::-;;108782:21;108795:7;108782:12;:21::i;:::-;108775:28;;108653:158;;;:::o;108472:115::-;108544:35;108553:2;108557:7;108566:12;:10;:12::i;:::-;108544:8;:35::i;:::-;108472:115;;:::o;135590:26::-;;;;:::o;135547:36::-;;;;;;;;;;;;;:::o;109322:588::-;109431:1;109417:16;;:2;:16;;;109413:89;;109487:1;109457:33;;;;;;;;;;;:::i;:::-;;;;;;;;109413:89;109723:21;109747:34;109755:2;109759:7;109768:12;:10;:12::i;:::-;109747:7;:34::i;:::-;109723:58;;109813:4;109796:21;;:13;:21;;;109792:111;;109862:4;109868:7;109877:13;109841:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;109792:111;109402:508;109322:588;;;:::o;130769:673::-;130880:16;130898:14;130925:32;130960:17;:26;130978:7;130960:26;;;;;;;;;;;130925:61;;130997:23;131023:12;:21;;;;;;;;;;;;130997:47;;131055:22;131080:12;:28;;;;;;;;;;;;131055:53;;131152:1;131125:29;;:15;:29;;;131121:176;;131189:19;:28;;;;;;;;;;;;131171:46;;131250:19;:35;;;;;;;;;;;;131232:53;;131121:176;131309:21;131365:17;:15;:17::i;:::-;131333:49;;131346:15;131334:27;;:9;:27;;;;:::i;:::-;131333:49;;;;:::i;:::-;131309:73;;131403:15;131420:13;131395:39;;;;;;;;130769:673;;;;;:::o;135623:41::-;135660:4;135623:41;:::o;109981:134::-;110068:39;110085:4;110091:2;110095:7;110068:39;;;;;;;;;;;;:16;:39::i;:::-;109981:134;;;:::o;135936:48::-;;;;;;;;;;;;;;;;;;;;;;:::o;107294:120::-;107357:7;107384:22;107398:7;107384:13;:22::i;:::-;107377:29;;107294:120;;;:::o;107019:213::-;107082:7;107123:1;107106:19;;:5;:19;;;107102:89;;107176:1;107149:30;;;;;;;;;;;:::i;:::-;;;;;;;;107102:89;107208:9;:16;107218:5;107208:16;;;;;;;;;;;;;;;;107201:23;;107019:213;;;:::o;135991:41::-;;;;;;;;;;;;;;;;;:::o;107641:95::-;107688:13;107721:7;107714:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;107641:95;:::o;108883:146::-;108969:52;108988:12;:10;:12::i;:::-;109002:8;109012;108969:18;:52::i;:::-;108883:146;;:::o;110186:236::-;110300:31;110313:4;110319:2;110323:7;110300:12;:31::i;:::-;110342:72;110376:12;:10;:12::i;:::-;110390:4;110396:2;110400:7;110409:4;110342:33;:72::i;:::-;110186:236;;;;:::o;139730:1038::-;139795:13;139821:16;139829:7;139821;:16::i;:::-;;139882:20;139905:11;:20;139917:7;139905:20;;;;;;;;;;;139882:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;139936:17;139988:19;140010:6;:11;;;139988:33;;140032:20;140055:6;:12;;;140032:35;;140078:21;140102:6;:13;;;140078:37;;140126:17;140146:62;140156:9;140167:11;140180:12;140194:13;140146:9;:62::i;:::-;140126:82;;140219:24;140246:65;140259:9;140270:11;140283:12;140297:13;140246:12;:65::i;:::-;140219:92;;140322:18;140401:17;140410:7;140401:8;:17::i;:::-;140565:25;140585:3;140565:13;:25::i;:::-;140629:10;140350:306;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;140322:335;;140732:26;140752:4;140732:13;:26::i;:::-;140682:77;;;;;;;;:::i;:::-;;;;;;;;;;;;;140668:92;;;;;;;;;;139730:1038;;;:::o;135689:44::-;135730:3;135689:44;:::o;137813:1909::-;137886:16;137934:1;137923:8;:12;:42;;;;;135730:3;137939:8;:26;;137923:42;137915:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;135660:4;138036:8;138022:11;;:22;;;;:::i;:::-;:36;;138014:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;138110:25;138152:8;138138:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;138110:51;;138179:9;138174:1513;138198:8;138194:1;:12;138174:1513;;;138228:6;:18;138235:10;138228:18;;;;;;;;;;;;;;;;:20;;;;;;;;;:::i;:::-;;;;;;138263:15;138297:10;138330:19;138364:20;138399:21;138437:932;138445:5;138444:6;:22;;;;;138464:2;138454:7;:12;138444:22;138437:932;;;138487:12;138562:1;138547:12;:16;;;;:::i;:::-;138537:27;138566:10;138578:6;:18;138585:10;138578:18;;;;;;;;;;;;;;;;138598:7;138520:86;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;138510:97;;;;;;138502:106;;138487:121;;138627:16;138681:4;138664:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;138654:41;;;;;;138646:50;;138627:69;;138715:17;138770:4;138753:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;138743:42;;;;;;138735:51;;138715:71;;138805:18;138861:4;138844:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;138834:43;;;;;;138826:52;;138805:73;;138922:3;138911:8;:14;;;;:::i;:::-;138897:28;;138971:2;138959:9;:14;;;;:::i;:::-;138944:29;;139021:2;139008:10;:15;;;;:::i;:::-;138992:31;;139042:17;139089:11;139102:12;139116:13;139072:58;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;139062:69;;;;;;139042:89;;139155:16;:27;139172:9;139155:27;;;;;;;;;;;;;;;;;;;;;139150:204;;139237:4;139207:16;:27;139224:9;139207:27;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;139272:4;139264:12;;139150:204;;;139325:9;;;;;:::i;:::-;;;;139150:204;138468:901;;;;;138437:932;;;139391:5;139383:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;139463:11;;:13;;;;;;;;;:::i;:::-;;;;;;139491:15;139509:11;;139491:29;;139558:48;;;;;;;;139565:11;139558:48;;;;139578:12;139558:48;;;;139592:13;139558:48;;;139535:11;:20;139547:7;139535:20;;;;;;;;;;;:71;;;;;;;;;;;;;;;;;;;;;;;;;;;139621:18;139627:2;139631:7;139621:5;:18::i;:::-;139668:7;139654:8;139663:1;139654:11;;;;;;;;:::i;:::-;;;;;;;:21;;;;;138213:1474;;;;;;138208:3;;;;;:::i;:::-;;;;138174:1513;;;;139706:8;139699:15;;;137813:1909;;;;:::o;136329:1476::-;136379:7;135660:4;136407:11;;:24;136399:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;136465:6;:18;136472:10;136465:18;;;;;;;;;;;;;;;;:20;;;;;;;;;:::i;:::-;;;;;;136496:15;136526:10;136555:19;136585:20;136616:21;136650:872;136658:5;136657:6;:22;;;;;136677:2;136667:7;:12;136657:22;136650:872;;;136696:12;136771:1;136756:12;:16;;;;:::i;:::-;136746:27;136775:10;136787:6;:18;136794:10;136787:18;;;;;;;;;;;;;;;;136807:7;136729:86;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;136719:97;;;;;;136711:106;;136696:121;;136832:16;136886:4;136869:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;136859:41;;;;;;136851:50;;136832:69;;136916:17;136971:4;136954:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;136944:42;;;;;;136936:51;;136916:71;;137002:18;137058:4;137041:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;137031:43;;;;;;137023:52;;137002:73;;137115:3;137104:8;:14;;;;:::i;:::-;137090:28;;137160:2;137148:9;:14;;;;:::i;:::-;137133:29;;137206:2;137193:10;:15;;;;:::i;:::-;137177:31;;137223:17;137270:11;137283:12;137297:13;137253:58;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;137243:69;;;;;;137223:89;;137332:16;:27;137349:9;137332:27;;;;;;;;;;;;;;;;;;;;;137327:184;;137410:4;137380:16;:27;137397:9;137380:27;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;137441:4;137433:12;;137327:184;;;137486:9;;;;;:::i;:::-;;;;137327:184;136681:841;;;;;136650:872;;;137540:5;137532:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;137608:11;;:13;;;;;;;;;:::i;:::-;;;;;;137632:15;137650:11;;137632:29;;137695:48;;;;;;;;137702:11;137695:48;;;;137715:12;137695:48;;;;137729:13;137695:48;;;137672:11;:20;137684:7;137672:20;;;;;;;;;;;:71;;;;;;;;;;;;;;;;;;;;;;;;;;;137754:18;137760:2;137764:7;137754:5;:18::i;:::-;137790:7;137783:14;;;;;;;;136329:1476;;;:::o;135884:45::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;109100:155::-;109188:4;109212:18;:25;109231:5;109212:25;;;;;;;;;;;;;;;:35;109238:8;109212:35;;;;;;;;;;;;;;;;;;;;;;;;;109205:42;;109100:155;;;;:::o;134896:170::-;134998:4;135022:36;135046:11;135022:23;:36::i;:::-;135015:43;;134896:170;;;:::o;121704:247::-;121767:7;121787:13;121803:17;121812:7;121803:8;:17::i;:::-;121787:33;;121852:1;121835:19;;:5;:19;;;121831:90;;121901:7;121878:31;;;;;;;;;;;:::i;:::-;;;;;;;;121831:90;121938:5;121931:12;;;121704:247;;;:::o;111185:129::-;111255:7;111282:15;:24;111298:7;111282:24;;;;;;;;;;;;;;;;;;;;;111275:31;;111185:129;;;:::o;17169:98::-;17222:7;17249:10;17242:17;;17169:98;:::o;119936:122::-;120017:33;120026:2;120030:7;120039:4;120045;120017:8;:33::i;:::-;119936:122;;;:::o;114146:824::-;114232:7;114252:12;114267:17;114276:7;114267:8;:17::i;:::-;114252:32;;114363:1;114347:18;;:4;:18;;;114343:88;;114382:37;114399:4;114405;114411:7;114382:16;:37::i;:::-;114343:88;114494:1;114478:18;;:4;:18;;;114474:263;;114596:48;114613:1;114617:7;114634:1;114638:5;114596:8;:48::i;:::-;114709:1;114690:9;:15;114700:4;114690:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;114474:263;114767:1;114753:16;;:2;:16;;;114749:111;;114832:1;114815:9;:13;114825:2;114815:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;114749:111;114891:2;114872:7;:16;114880:7;114872:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;114930:7;114926:2;114911:27;;114920:4;114911:27;;;;;;;;;;;;114958:4;114951:11;;;114146:824;;;;;:::o;131724:97::-;131782:6;131808:5;131801:12;;131724:97;:::o;121143:318::-;121271:1;121251:22;;:8;:22;;;121247:93;;121319:8;121297:31;;;;;;;;;;;:::i;:::-;;;;;;;;121247:93;121388:8;121350:18;:25;121369:5;121350:25;;;;;;;;;;;;;;;:35;121376:8;121350:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;121434:8;121412:41;;121427:5;121412:41;;;121444:8;121412:41;;;;;;:::i;:::-;;;;;;;;121143:318;;;:::o;15519:948::-;15723:1;15706:2;:14;;;:18;15702:758;;;15761:2;15745:36;;;15782:8;15792:4;15798:7;15807:4;15745:67;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;15741:708;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16125:1;16108:6;:13;:18;16104:330;;16250:2;16214:39;;;;;;;;;;;:::i;:::-;;;;;;;;16104:330;16384:6;16378:13;16369:6;16365:2;16361:15;16354:38;15741:708;15870:41;;;15860:51;;;:6;:51;;;;15856:185;;16018:2;15982:39;;;;;;;;;;;:::i;:::-;;;;;;;;15856:185;15813:243;15702:758;15519:948;;;;;:::o;140776:756::-;140946:13;140972:19;140994:10;;;;;;;;;;;:22;;;141017:1;141020:9;140994:36;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140972:58;;141041:23;141067:10;;;;;;;;;;;:22;;;141090:1;141093:13;141067:40;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;141041:66;;141118:21;141142:10;;;;;;;;;;;:22;;;141165:1;141168:11;141142:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;141118:62;;141191:22;141216:10;;;;;;;;;;;:22;;;141239:1;141242:12;141216:39;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;141191:64;;141415:5;141435:9;141459:7;141481:8;141280:243;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;141266:258;;;;;;140776:756;;;;;;:::o;141540:592::-;141713:13;141739:20;141762:10;;;;;;;;;;;:24;;;141787:1;141790:9;141762:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;141739:61;;141844:6;141857:10;;;;;;;;;;;:24;;;141882:1;141885:11;141857:40;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;141827:71;;;;;;;;;:::i;:::-;;;;;;;;;;;;;141811:88;;141943:6;141956:10;;;;;;;;;;;:24;;;141981:1;141984:12;141956:41;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;141926:72;;;;;;;;;:::i;:::-;;;;;;;;;;;;;141910:89;;142043:6;142056:10;;;;;;;;;;;:24;;;142081:1;142084:13;142056:42;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;142026:73;;;;;;;;;:::i;:::-;;;;;;;;;;;;;142010:90;;142118:6;142111:13;;;141540:592;;;;;;:::o;142140:496::-;142196:13;142235:1;142226:5;:10;142222:26;;142238:10;;;;;;;;;;;;;;;;;;;;;142222:26;142259:12;142274:5;142259:20;;142290:14;142315:78;142330:1;142322:4;:9;142315:78;;142348:8;;;;;:::i;:::-;;;;142379:2;142371:10;;;;;:::i;:::-;;;142315:78;;;142403:19;142435:6;142425:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;142403:39;;142453:144;142469:1;142460:5;:10;142453:144;;142487:8;;;;;:::i;:::-;;;;142554:2;142546:5;:10;;;;:::i;:::-;142540:2;:17;;;;:::i;:::-;142527:32;;142510:6;142517;142510:14;;;;;;;;:::i;:::-;;;;;:49;;;;;;;;;;;142583:2;142574:11;;;;;:::i;:::-;;;142453:144;;;142621:6;142607:21;;;;;142140:496;;;;:::o;122662:126::-;122720:13;122753:27;122761:4;122767:6;;;;;;;;;;;;;;;;;122775:4;122753:7;:27::i;:::-;122746:34;;122662:126;;;:::o;115306:335::-;115388:1;115374:16;;:2;:16;;;115370:89;;115444:1;115414:33;;;;;;;;;;;:::i;:::-;;;;;;;;115370:89;115469:21;115493:32;115501:2;115505:7;115522:1;115493:7;:32::i;:::-;115469:56;;115565:1;115540:27;;:13;:27;;;115536:98;;115619:1;115591:31;;;;;;;;;;;:::i;:::-;;;;;;;;115536:98;115359:282;115306:335;;:::o;106650:305::-;106752:4;106804:25;106789:40;;;:11;:40;;;;:105;;;;106861:33;106846:48;;;:11;:48;;;;106789:105;:158;;;;106911:36;106935:11;106911:23;:36::i;:::-;106789:158;106769:178;;106650:305;;;:::o;110947:117::-;111013:7;111040;:16;111048:7;111040:16;;;;;;;;;;;;;;;;;;;;;111033:23;;110947:117;;;:::o;120246:678::-;120408:9;:31;;;;120437:1;120421:18;;:4;:18;;;;120408:31;120404:471;;;120456:13;120472:22;120486:7;120472:13;:22::i;:::-;120456:38;;120641:1;120625:18;;:4;:18;;;;:35;;;;;120656:4;120647:13;;:5;:13;;;;120625:35;:69;;;;;120665:29;120682:5;120689:4;120665:16;:29::i;:::-;120664:30;120625:69;120621:144;;;120744:4;120722:27;;;;;;;;;;;:::i;:::-;;;;;;;;120621:144;120785:9;120781:83;;;120840:7;120836:2;120820:28;;120829:5;120820:28;;;;;;;;;;;;120781:83;120441:434;120404:471;120914:2;120887:15;:24;120903:7;120887:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;120246:678;;;;:::o;112353:376::-;112466:38;112480:5;112487:7;112496;112466:13;:38::i;:::-;112461:261;;112542:1;112525:19;;:5;:19;;;112521:190;;112595:7;112572:31;;;;;;;;;;;:::i;:::-;;;;;;;;112521:190;112678:7;112687;112651:44;;;;;;;;;;;;:::i;:::-;;;;;;;;112461:261;112353:376;;;:::o;123200:4109::-;123297:13;123549:1;123534:4;:11;:16;123530:31;;123552:9;;;;;;;;;;;;;;;;123530:31;124514:20;124537:11;:69;;124605:1;124600;124586:4;:11;124582:1;:15;;;;:::i;:::-;:19;;;;:::i;:::-;124581:25;;;;:::i;:::-;124537:69;;;124576:1;124571;124557:4;:11;:15;;;;:::i;:::-;124556:21;;;;:::i;:::-;124551:1;:27;;;;:::i;:::-;124537:69;124514:92;;124619:20;124653:12;124642:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124619:47;;124818:1;124811:5;124807:13;124922:4;124914:6;124910:17;124956:4;125004;124998:11;124992:4;124988:22;125256:4;125248:6;125244:17;125299:8;125293:15;125339:4;125329:8;125322:22;125414:1286;125449:6;125440:7;125437:19;125414:1286;;;125555:1;125546:7;125542:15;125531:26;;125594:7;125588:14;126190:4;126182:5;126178:2;126174:14;126170:25;126160:8;126156:40;126150:47;126139:9;126131:67;126244:1;126233:9;126229:17;126216:30;;126336:4;126328:5;126324:2;126320:14;126316:25;126306:8;126302:40;126296:47;126285:9;126277:67;126390:1;126379:9;126375:17;126362:30;;126481:4;126473:5;126470:1;126466:13;126462:24;126452:8;126448:39;126442:46;126431:9;126423:66;126535:1;126524:9;126520:17;126507:30;;126618:4;126611:5;126607:16;126597:8;126593:31;126587:38;126576:9;126568:58;126672:1;126661:9;126657:17;126644:30;;125476:1224;125414:1286;;;126781:10;126771:8;126764:28;126811:11;126808:457;;;126996:1;126989:4;126983:11;126979:19;127021:1;127016:135;;;;127174:1;127169:81;;;;126972:278;;127016:135;127073:4;127069:1;127058:9;127054:17;127046:32;127127:4;127123:1;127112:9;127108:17;127100:32;127016:135;;127169:81;127226:4;127222:1;127211:9;127207:17;127199:32;126972:278;;126808:457;124704:2572;;;;;;127295:6;127288:13;;;;123200:4109;;;;;;:::o;130499:215::-;130601:4;130640:26;130625:41;;;:11;:41;;;;:81;;;;130670:36;130694:11;130670:23;:36::i;:::-;130625:81;130618:88;;130499:215;;;:::o;111634:276::-;111737:4;111793:1;111774:21;;:7;:21;;;;:128;;;;;111822:7;111813:16;;:5;:16;;;:52;;;;111833:32;111850:5;111857:7;111833:16;:32::i;:::-;111813:52;:88;;;;111894:7;111869:32;;:21;111882:7;111869:12;:21::i;:::-;:32;;;111813:88;111774:128;111754:148;;111634:276;;;;;:::o;105248:148::-;105324:4;105363:25;105348:40;;;:11;:40;;;;105341:47;;105248: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:246::-;1879:1;1889:113;1903:6;1900:1;1897:13;1889:113;;;1988:1;1983:3;1979:11;1973:18;1969:1;1964:3;1960:11;1953:39;1925:2;1922:1;1918:10;1913:15;;1889:113;;;2036:1;2027:6;2022:3;2018:16;2011:27;1860:184;1798:246;;;:::o;2050:102::-;2091:6;2142:2;2138:7;2133:2;2126:5;2122:14;2118:28;2108:38;;2050:102;;;:::o;2158:377::-;2246:3;2274:39;2307:5;2274:39;:::i;:::-;2329:71;2393:6;2388:3;2329:71;:::i;:::-;2322:78;;2409:65;2467:6;2462:3;2455:4;2448:5;2444:16;2409:65;:::i;:::-;2499:29;2521:6;2499:29;:::i;:::-;2494:3;2490:39;2483:46;;2250:285;2158:377;;;;:::o;2541:313::-;2654:4;2692:2;2681:9;2677:18;2669:26;;2741:9;2735:4;2731:20;2727:1;2716:9;2712:17;2705:47;2769:78;2842:4;2833:6;2769:78;:::i;:::-;2761:86;;2541:313;;;;:::o;2860:77::-;2897:7;2926:5;2915:16;;2860:77;;;:::o;2943:122::-;3016:24;3034:5;3016:24;:::i;:::-;3009:5;3006:35;2996:63;;3055:1;3052;3045:12;2996:63;2943:122;:::o;3071:139::-;3117:5;3155:6;3142:20;3133:29;;3171:33;3198:5;3171:33;:::i;:::-;3071:139;;;;:::o;3216:329::-;3275:6;3324:2;3312:9;3303:7;3299:23;3295:32;3292:119;;;3330:79;;:::i;:::-;3292:119;3450:1;3475:53;3520:7;3511:6;3500:9;3496:22;3475:53;:::i;:::-;3465:63;;3421:117;3216:329;;;;:::o;3551:126::-;3588:7;3628:42;3621:5;3617:54;3606:65;;3551:126;;;:::o;3683:96::-;3720:7;3749:24;3767:5;3749:24;:::i;:::-;3738:35;;3683:96;;;:::o;3785:118::-;3872:24;3890:5;3872:24;:::i;:::-;3867:3;3860:37;3785:118;;:::o;3909:222::-;4002:4;4040:2;4029:9;4025:18;4017:26;;4053:71;4121:1;4110:9;4106:17;4097:6;4053:71;:::i;:::-;3909:222;;;;:::o;4137:122::-;4210:24;4228:5;4210:24;:::i;:::-;4203:5;4200:35;4190:63;;4249:1;4246;4239:12;4190:63;4137:122;:::o;4265:139::-;4311:5;4349:6;4336:20;4327:29;;4365:33;4392:5;4365:33;:::i;:::-;4265:139;;;;:::o;4410:474::-;4478:6;4486;4535:2;4523:9;4514:7;4510:23;4506:32;4503:119;;;4541:79;;:::i;:::-;4503:119;4661:1;4686:53;4731:7;4722:6;4711:9;4707:22;4686:53;:::i;:::-;4676:63;;4632:117;4788:2;4814:53;4859:7;4850:6;4839:9;4835:22;4814:53;:::i;:::-;4804:63;;4759:118;4410:474;;;;;:::o;4890:118::-;4977:24;4995:5;4977:24;:::i;:::-;4972:3;4965:37;4890:118;;:::o;5014:222::-;5107:4;5145:2;5134:9;5130:18;5122:26;;5158:71;5226:1;5215:9;5211:17;5202:6;5158:71;:::i;:::-;5014:222;;;;:::o;5242:60::-;5270:3;5291:5;5284:12;;5242:60;;;:::o;5308:142::-;5358:9;5391:53;5409:34;5418:24;5436:5;5418:24;:::i;:::-;5409:34;:::i;:::-;5391:53;:::i;:::-;5378:66;;5308:142;;;:::o;5456:126::-;5506:9;5539:37;5570:5;5539:37;:::i;:::-;5526:50;;5456:126;;;:::o;5588:153::-;5665:9;5698:37;5729:5;5698:37;:::i;:::-;5685:50;;5588:153;;;:::o;5747:185::-;5861:64;5919:5;5861:64;:::i;:::-;5856:3;5849:77;5747:185;;:::o;5938:276::-;6058:4;6096:2;6085:9;6081:18;6073:26;;6109:98;6204:1;6193:9;6189:17;6180:6;6109:98;:::i;:::-;5938:276;;;;:::o;6220:619::-;6297:6;6305;6313;6362:2;6350:9;6341:7;6337:23;6333:32;6330:119;;;6368:79;;:::i;:::-;6330:119;6488:1;6513:53;6558:7;6549:6;6538:9;6534:22;6513:53;:::i;:::-;6503:63;;6459:117;6615:2;6641:53;6686:7;6677:6;6666:9;6662:22;6641:53;:::i;:::-;6631:63;;6586:118;6743:2;6769:53;6814:7;6805:6;6794:9;6790:22;6769:53;:::i;:::-;6759:63;;6714:118;6220:619;;;;;:::o;6845:474::-;6913:6;6921;6970:2;6958:9;6949:7;6945:23;6941:32;6938:119;;;6976:79;;:::i;:::-;6938:119;7096:1;7121:53;7166:7;7157:6;7146:9;7142:22;7121:53;:::i;:::-;7111:63;;7067:117;7223:2;7249:53;7294:7;7285:6;7274:9;7270:22;7249:53;:::i;:::-;7239:63;;7194:118;6845:474;;;;;:::o;7325:332::-;7446:4;7484:2;7473:9;7469:18;7461:26;;7497:71;7565:1;7554:9;7550:17;7541:6;7497:71;:::i;:::-;7578:72;7646:2;7635:9;7631:18;7622:6;7578:72;:::i;:::-;7325:332;;;;;:::o;7663:77::-;7700:7;7729:5;7718:16;;7663:77;;;:::o;7746:122::-;7819:24;7837:5;7819:24;:::i;:::-;7812:5;7809:35;7799:63;;7858:1;7855;7848:12;7799:63;7746:122;:::o;7874:139::-;7920:5;7958:6;7945:20;7936:29;;7974:33;8001:5;7974:33;:::i;:::-;7874:139;;;;:::o;8019:329::-;8078:6;8127:2;8115:9;8106:7;8102:23;8098:32;8095:119;;;8133:79;;:::i;:::-;8095:119;8253:1;8278:53;8323:7;8314:6;8303:9;8299:22;8278:53;:::i;:::-;8268:63;;8224:117;8019:329;;;;:::o;8354:::-;8413:6;8462:2;8450:9;8441:7;8437:23;8433:32;8430:119;;;8468:79;;:::i;:::-;8430:119;8588:1;8613:53;8658:7;8649:6;8638:9;8634:22;8613:53;:::i;:::-;8603:63;;8559:117;8354:329;;;;:::o;8689:116::-;8759:21;8774:5;8759:21;:::i;:::-;8752:5;8749:32;8739:60;;8795:1;8792;8785:12;8739:60;8689:116;:::o;8811:133::-;8854:5;8892:6;8879:20;8870:29;;8908:30;8932:5;8908:30;:::i;:::-;8811:133;;;;:::o;8950:468::-;9015:6;9023;9072:2;9060:9;9051:7;9047:23;9043:32;9040:119;;;9078:79;;:::i;:::-;9040:119;9198:1;9223:53;9268:7;9259:6;9248:9;9244:22;9223:53;:::i;:::-;9213:63;;9169:117;9325:2;9351:50;9393:7;9384:6;9373:9;9369:22;9351:50;:::i;:::-;9341:60;;9296:115;8950:468;;;;;:::o;9424:117::-;9533:1;9530;9523:12;9547:117;9656:1;9653;9646:12;9670:180;9718:77;9715:1;9708:88;9815:4;9812:1;9805:15;9839:4;9836:1;9829:15;9856:281;9939:27;9961:4;9939:27;:::i;:::-;9931:6;9927:40;10069:6;10057:10;10054:22;10033:18;10021:10;10018:34;10015:62;10012:88;;;10080:18;;:::i;:::-;10012:88;10120:10;10116:2;10109:22;9899:238;9856:281;;:::o;10143:129::-;10177:6;10204:20;;:::i;:::-;10194:30;;10233:33;10261:4;10253:6;10233:33;:::i;:::-;10143:129;;;:::o;10278:307::-;10339:4;10429:18;10421:6;10418:30;10415:56;;;10451:18;;:::i;:::-;10415:56;10489:29;10511:6;10489:29;:::i;:::-;10481:37;;10573:4;10567;10563:15;10555:23;;10278:307;;;:::o;10591:146::-;10688:6;10683:3;10678;10665:30;10729:1;10720:6;10715:3;10711:16;10704:27;10591:146;;;:::o;10743:423::-;10820:5;10845:65;10861:48;10902:6;10861:48;:::i;:::-;10845:65;:::i;:::-;10836:74;;10933:6;10926:5;10919:21;10971:4;10964:5;10960:16;11009:3;11000:6;10995:3;10991:16;10988:25;10985:112;;;11016:79;;:::i;:::-;10985:112;11106:54;11153:6;11148:3;11143;11106:54;:::i;:::-;10826:340;10743:423;;;;;:::o;11185:338::-;11240:5;11289:3;11282:4;11274:6;11270:17;11266:27;11256:122;;11297:79;;:::i;:::-;11256:122;11414:6;11401:20;11439:78;11513:3;11505:6;11498:4;11490:6;11486:17;11439:78;:::i;:::-;11430:87;;11246:277;11185:338;;;;:::o;11529:943::-;11624:6;11632;11640;11648;11697:3;11685:9;11676:7;11672:23;11668:33;11665:120;;;11704:79;;:::i;:::-;11665:120;11824:1;11849:53;11894:7;11885:6;11874:9;11870:22;11849:53;:::i;:::-;11839:63;;11795:117;11951:2;11977:53;12022:7;12013:6;12002:9;11998:22;11977:53;:::i;:::-;11967:63;;11922:118;12079:2;12105:53;12150:7;12141:6;12130:9;12126:22;12105:53;:::i;:::-;12095:63;;12050:118;12235:2;12224:9;12220:18;12207:32;12266:18;12258:6;12255:30;12252:117;;;12288:79;;:::i;:::-;12252:117;12393:62;12447:7;12438:6;12427:9;12423:22;12393:62;:::i;:::-;12383:72;;12178:287;11529:943;;;;;;;:::o;12478:114::-;12545:6;12579:5;12573:12;12563:22;;12478:114;;;:::o;12598:184::-;12697:11;12731:6;12726:3;12719:19;12771:4;12766:3;12762:14;12747:29;;12598:184;;;;:::o;12788:132::-;12855:4;12878:3;12870:11;;12908:4;12903:3;12899:14;12891:22;;12788:132;;;:::o;12926:108::-;13003:24;13021:5;13003:24;:::i;:::-;12998:3;12991:37;12926:108;;:::o;13040:179::-;13109:10;13130:46;13172:3;13164:6;13130:46;:::i;:::-;13208:4;13203:3;13199:14;13185:28;;13040:179;;;;:::o;13225:113::-;13295:4;13327;13322:3;13318:14;13310:22;;13225:113;;;:::o;13374:732::-;13493:3;13522:54;13570:5;13522:54;:::i;:::-;13592:86;13671:6;13666:3;13592:86;:::i;:::-;13585:93;;13702:56;13752:5;13702:56;:::i;:::-;13781:7;13812:1;13797:284;13822:6;13819:1;13816:13;13797:284;;;13898:6;13892:13;13925:63;13984:3;13969:13;13925:63;:::i;:::-;13918:70;;14011:60;14064:6;14011:60;:::i;:::-;14001:70;;13857:224;13844:1;13841;13837:9;13832:14;;13797:284;;;13801:14;14097:3;14090:10;;13498:608;;;13374:732;;;;:::o;14112:373::-;14255:4;14293:2;14282:9;14278:18;14270:26;;14342:9;14336:4;14332:20;14328:1;14317:9;14313:17;14306:47;14370:108;14473:4;14464:6;14370:108;:::i;:::-;14362:116;;14112:373;;;;:::o;14491:442::-;14640:4;14678:2;14667:9;14663:18;14655:26;;14691:71;14759:1;14748:9;14744:17;14735:6;14691:71;:::i;:::-;14772:72;14840:2;14829:9;14825:18;14816:6;14772:72;:::i;:::-;14854;14922:2;14911:9;14907:18;14898:6;14854:72;:::i;:::-;14491:442;;;;;;:::o;14939:474::-;15007:6;15015;15064:2;15052:9;15043:7;15039:23;15035:32;15032:119;;;15070:79;;:::i;:::-;15032:119;15190:1;15215:53;15260:7;15251:6;15240:9;15236:22;15215:53;:::i;:::-;15205:63;;15161:117;15317:2;15343:53;15388:7;15379:6;15368:9;15364:22;15343:53;:::i;:::-;15333:63;;15288:118;14939:474;;;;;:::o;15419:180::-;15467:77;15464:1;15457:88;15564:4;15561:1;15554:15;15588:4;15585:1;15578:15;15605:320;15649:6;15686:1;15680:4;15676:12;15666:22;;15733:1;15727:4;15723:12;15754:18;15744:81;;15810:4;15802:6;15798:17;15788:27;;15744:81;15872:2;15864:6;15861:14;15841:18;15838:38;15835:84;;15891:18;;:::i;:::-;15835:84;15656:269;15605:320;;;:::o;15931:442::-;16080:4;16118:2;16107:9;16103:18;16095:26;;16131:71;16199:1;16188:9;16184:17;16175:6;16131:71;:::i;:::-;16212:72;16280:2;16269:9;16265:18;16256:6;16212:72;:::i;:::-;16294;16362:2;16351:9;16347:18;16338:6;16294:72;:::i;:::-;15931:442;;;;;;:::o;16379:180::-;16427:77;16424:1;16417:88;16524:4;16521:1;16514:15;16548:4;16545:1;16538:15;16565:410;16605:7;16628:20;16646:1;16628:20;:::i;:::-;16623:25;;16662:20;16680:1;16662:20;:::i;:::-;16657:25;;16717:1;16714;16710:9;16739:30;16757:11;16739:30;:::i;:::-;16728:41;;16918:1;16909:7;16905:15;16902:1;16899:22;16879:1;16872:9;16852:83;16829:139;;16948:18;;:::i;:::-;16829:139;16613:362;16565:410;;;;:::o;16981:180::-;17029:77;17026:1;17019:88;17126:4;17123:1;17116:15;17150:4;17147:1;17140:15;17167:185;17207:1;17224:20;17242:1;17224:20;:::i;:::-;17219:25;;17258:20;17276:1;17258:20;:::i;:::-;17253:25;;17297:1;17287:35;;17302:18;;:::i;:::-;17287:35;17344:1;17341;17337:9;17332:14;;17167:185;;;;:::o;17358:148::-;17460:11;17497:3;17482:18;;17358:148;;;;:::o;17512:214::-;17652:66;17648:1;17640:6;17636:14;17629:90;17512:214;:::o;17732:402::-;17892:3;17913:85;17995:2;17990:3;17913:85;:::i;:::-;17906:92;;18007:93;18096:3;18007:93;:::i;:::-;18125:2;18120:3;18116:12;18109:19;;17732:402;;;:::o;18140:390::-;18246:3;18274:39;18307:5;18274:39;:::i;:::-;18329:89;18411:6;18406:3;18329:89;:::i;:::-;18322:96;;18427:65;18485:6;18480:3;18473:4;18466:5;18462:16;18427:65;:::i;:::-;18517:6;18512:3;18508:16;18501:23;;18250:280;18140:390;;;;:::o;18536:214::-;18676:66;18672:1;18664:6;18660:14;18653:90;18536:214;:::o;18756:400::-;18916:3;18937:84;19019:1;19014:3;18937:84;:::i;:::-;18930:91;;19030:93;19119:3;19030:93;:::i;:::-;19148:1;19143:3;19139:11;19132:18;;18756:400;;;:::o;19162:384::-;19302:66;19298:1;19290:6;19286:14;19279:90;19403:34;19398:2;19390:6;19386:15;19379:59;19472:66;19467:2;19459:6;19455:15;19448:91;19162:384;:::o;19552:402::-;19712:3;19733:85;19815:2;19810:3;19733:85;:::i;:::-;19726:92;;19827:93;19916:3;19827:93;:::i;:::-;19945:2;19940:3;19936:12;19929:19;;19552:402;;;:::o;19960:254::-;20100:66;20096:1;20088:6;20084:14;20077:90;20201:5;20196:2;20188:6;20184:15;20177:30;19960:254;:::o;20220:402::-;20380:3;20401:85;20483:2;20478:3;20401:85;:::i;:::-;20394:92;;20495:93;20584:3;20495:93;:::i;:::-;20613:2;20608:3;20604:12;20597:19;;20220:402;;;:::o;20628:214::-;20768:66;20764:1;20756:6;20752:14;20745:90;20628:214;:::o;20848:402::-;21008:3;21029:85;21111:2;21106:3;21029:85;:::i;:::-;21022:92;;21123:93;21212:3;21123:93;:::i;:::-;21241:2;21236:3;21232:12;21225:19;;20848:402;;;:::o;21256:144::-;21392:4;21388:1;21380:6;21376:14;21369:28;21256:144;:::o;21402:384::-;21562:3;21579:84;21661:1;21656:3;21579:84;:::i;:::-;21572:91;;21668:93;21757:3;21668:93;:::i;:::-;21782:1;21777:3;21773:11;21766:18;;21402:384;;;:::o;21788:2409::-;22723:3;22741:148;22885:3;22741:148;:::i;:::-;22734:155;;22902:95;22993:3;22984:6;22902:95;:::i;:::-;22895:102;;23010:148;23154:3;23010:148;:::i;:::-;23003:155;;23171:148;23315:3;23171:148;:::i;:::-;23164:155;;23332:148;23476:3;23332:148;:::i;:::-;23325:155;;23493:95;23584:3;23575:6;23493:95;:::i;:::-;23486:102;;23601:148;23745:3;23601:148;:::i;:::-;23594:155;;23762:148;23906:3;23762:148;:::i;:::-;23755:155;;23923:95;24014:3;24005:6;23923:95;:::i;:::-;23916:102;;24031:148;24175:3;24031:148;:::i;:::-;24024:155;;24192:3;24185:10;;21788:2409;;;;;;:::o;24199:171::-;24335:31;24331:1;24323:6;24319:14;24312:55;24199:171;:::o;24372:386::-;24532:3;24549:85;24631:2;24626:3;24549:85;:::i;:::-;24542:92;;24639:93;24728:3;24639:93;:::i;:::-;24753:2;24748:3;24744:12;24737:19;;24372:386;;;:::o;24760:525::-;24993:3;25011:148;25155:3;25011:148;:::i;:::-;25004:155;;25172:95;25263:3;25254:6;25172:95;:::i;:::-;25165:102;;25280:3;25273:10;;24760:525;;;;:::o;25287:208::-;25423:34;25419:1;25411:6;25407:14;25400:58;25488:3;25483:2;25475:6;25471:15;25464:28;25287:208;:::o;25497:350::-;25639:3;25656:67;25720:2;25715:3;25656:67;:::i;:::-;25649:74;;25728:93;25817:3;25728:93;:::i;:::-;25842:2;25837:3;25833:12;25826:19;;25497:350;;;:::o;25849:403::-;26015:4;26049:2;26038:9;26034:18;26026:26;;26094:9;26088:4;26084:20;26080:1;26069:9;26065:17;26058:47;26118:131;26244:4;26118:131;:::i;:::-;26110:139;;25849:403;;;:::o;26254:171::-;26294:3;26309:20;26327:1;26309:20;:::i;:::-;26304:25;;26339:20;26357:1;26339:20;:::i;:::-;26334:25;;26378:1;26375;26371:9;26364:16;;26395:3;26392:1;26389:10;26386:36;;;26402:18;;:::i;:::-;26386:36;26254:171;;;;:::o;26427:209::-;26563:34;26559:1;26551:6;26547:14;26540:58;26628:4;26623:2;26615:6;26611:15;26604:29;26427:209;:::o;26638:350::-;26780:3;26797:67;26861:2;26856:3;26797:67;:::i;:::-;26790:74;;26869:93;26958:3;26869:93;:::i;:::-;26983:2;26978:3;26974:12;26967:19;;26638:350;;;:::o;26990:403::-;27156:4;27190:2;27179:9;27175:18;27167:26;;27235:9;27229:4;27225:20;27221:1;27210:9;27206:17;27199:47;27259:131;27385:4;27259:131;:::i;:::-;27251:139;;26990:403;;;:::o;27395:217::-;27434:3;27453:24;27471:5;27453:24;:::i;:::-;27444:33;;27495:66;27488:5;27485:77;27482:103;;27565:18;;:::i;:::-;27482:103;27608:1;27601:5;27597:13;27590:20;;27395:217;;;:::o;27614:174::-;27654:4;27670:20;27688:1;27670:20;:::i;:::-;27665:25;;27700:20;27718:1;27700:20;:::i;:::-;27695:25;;27740:1;27737;27733:9;27725:17;;27760:1;27754:4;27751:11;27748:37;;;27765:18;;:::i;:::-;27748:37;27614:174;;;;:::o;27790:71::-;27829:7;27854:5;27843:16;;27790:71;;;:::o;27863:149::-;27964:45;27984:24;28002:5;27984:24;:::i;:::-;27964:45;:::i;:::-;27959:3;27952:58;27863:149;;:::o;28014:82::-;28047:8;28087:5;28083:2;28079:14;28062:31;;28014:82;;;:::o;28098:86::-;28137:7;28162:20;28176:5;28162:20;:::i;:::-;28151:31;;28098:86;;;:::o;28186:92::-;28225:7;28250:26;28270:5;28250:26;:::i;:::-;28239:37;;28186:92;;;:::o;28280:149::-;28381:45;28401:24;28419:5;28401:24;:::i;:::-;28381:45;:::i;:::-;28376:3;28369:58;28280:149;;:::o;28431:71::-;28470:7;28495:5;28484:16;;28431:71;;;:::o;28504:149::-;28605:45;28625:24;28643:5;28625:24;:::i;:::-;28605:45;:::i;:::-;28600:3;28593:58;28504:149;;:::o;28655:639::-;28851:3;28862:75;28933:3;28924:6;28862:75;:::i;:::-;28958:2;28953:3;28949:12;28942:19;;28967:75;29038:3;29029:6;28967:75;:::i;:::-;29063:2;29058:3;29054:12;29047:19;;29072:75;29143:3;29134:6;29072:75;:::i;:::-;29168:2;29163:3;29159:12;29152:19;;29177:75;29248:3;29239:6;29177:75;:::i;:::-;29273:2;29268:3;29264:12;29257:19;;29289:3;29282:10;;28655:639;;;;;;;:::o;29296:146::-;29432:6;29428:1;29420:6;29416:14;29409:30;29296:146;:::o;29444:384::-;29604:3;29621:84;29703:1;29698:3;29621:84;:::i;:::-;29614:91;;29710:93;29799:3;29710:93;:::i;:::-;29824:1;29819:3;29815:11;29808:18;;29444:384;;;:::o;29830:502::-;30043:3;30054:75;30125:3;30116:6;30054:75;:::i;:::-;30150:2;30145:3;30141:12;30134:19;;30166:148;30310:3;30166:148;:::i;:::-;30159:155;;30327:3;30320:10;;29830:502;;;;:::o;30334:147::-;30470:7;30466:1;30458:6;30454:14;30447:31;30334:147;:::o;30483:384::-;30643:3;30660:84;30742:1;30737:3;30660:84;:::i;:::-;30653:91;;30749:93;30838:3;30749:93;:::i;:::-;30863:1;30858:3;30854:11;30847:18;;30483:384;;;:::o;30869:502::-;31082:3;31093:75;31164:3;31155:6;31093:75;:::i;:::-;31189:2;31184:3;31180:12;31173:19;;31205:148;31349:3;31205:148;:::i;:::-;31198:155;;31366:3;31359:10;;30869:502;;;;:::o;31373:148::-;31509:8;31505:1;31497:6;31493:14;31486:32;31373:148;:::o;31523:384::-;31683:3;31700:84;31782:1;31777:3;31700:84;:::i;:::-;31693:91;;31789:93;31878:3;31789:93;:::i;:::-;31903:1;31898:3;31894:11;31887:18;;31523:384;;;:::o;31909:502::-;32122:3;32133:75;32204:3;32195:6;32133:75;:::i;:::-;32229:2;32224:3;32220:12;32213:19;;32245:148;32389:3;32245:148;:::i;:::-;32238:155;;32406:3;32399:10;;31909:502;;;;:::o;32413:156::-;32445:1;32458:20;32476:1;32458:20;:::i;:::-;32453:25;;32488:20;32506:1;32488:20;:::i;:::-;32483:25;;32523:1;32513:35;;32528:18;;:::i;:::-;32513:35;32565:1;32562;32558:9;32553:14;;32413:156;;;;:::o;32571:506::-;32739:3;32750:75;32821:3;32812:6;32750:75;:::i;:::-;32846:2;32841:3;32837:12;32830:19;;32855:75;32926:3;32917:6;32855:75;:::i;:::-;32951:2;32946:3;32942:12;32935:19;;32960:75;33031:3;33022:6;32960:75;:::i;:::-;33056:2;33051:3;33047:12;33040:19;;33072:3;33065:10;;32571:506;;;;;;:::o;33079:220::-;33215:34;33211:1;33203:6;33199:14;33192:58;33280:15;33275:2;33267:6;33263:15;33256:40;33079:220;:::o;33301:350::-;33443:3;33460:67;33524:2;33519:3;33460:67;:::i;:::-;33453:74;;33532:93;33621:3;33532:93;:::i;:::-;33646:2;33641:3;33637:12;33630:19;;33301:350;;;:::o;33653:403::-;33819:4;33853:2;33842:9;33838:18;33830:26;;33898:9;33892:4;33888:20;33884:1;33873:9;33869:17;33862:47;33922:131;34048:4;33922:131;:::i;:::-;33914:139;;33653:403;;;:::o;34058:164::-;34102:77;34099:1;34092:88;34195:4;34192:1;34185:15;34215:4;34212:1;34205:15;34224:160;34360:20;34356:1;34348:6;34344:14;34337:44;34224:160;:::o;34386:350::-;34528:3;34545:67;34609:2;34604:3;34545:67;:::i;:::-;34538:74;;34617:93;34706:3;34617:93;:::i;:::-;34731:2;34726:3;34722:12;34715:19;;34386:350;;;:::o;34738:403::-;34904:4;34938:2;34927:9;34923:18;34915:26;;34983:9;34977:4;34973:20;34969:1;34958:9;34954:17;34947:47;35007:131;35133:4;35007:131;:::i;:::-;34999:139;;34738:403;;;:::o;35143:90::-;35194:6;35224:5;35218:12;35208:22;;35143:90;;;:::o;35235:156::-;35318:11;35348:6;35343:3;35336:19;35384:4;35379:3;35375:14;35360:29;;35235:156;;;;:::o;35393:353::-;35479:3;35503:38;35535:5;35503:38;:::i;:::-;35553:70;35616:6;35611:3;35553:70;:::i;:::-;35546:77;;35628:65;35686:6;35681:3;35674:4;35667:5;35663:16;35628:65;:::i;:::-;35714:29;35736:6;35714:29;:::i;:::-;35709:3;35705:39;35698:46;;35483:263;35393:353;;;;:::o;35748:612::-;35943:4;35977:3;35966:9;35962:19;35954:27;;35987:71;36055:1;36044:9;36040:17;36031:6;35987:71;:::i;:::-;36064:72;36132:2;36121:9;36117:18;36108:6;36064:72;:::i;:::-;36142;36210:2;36199:9;36195:18;36186:6;36142:72;:::i;:::-;36257:9;36251:4;36247:20;36242:2;36231:9;36227:18;36220:48;36281:76;36352:4;36343:6;36281:76;:::i;:::-;36273:84;;35748:612;;;;;;;:::o;36362:129::-;36418:5;36445:6;36439:13;36430:22;;36457:32;36483:5;36457:32;:::i;:::-;36362:129;;;;:::o;36493:325::-;36562:6;36607:2;36595:9;36586:7;36582:23;36578:32;36575:119;;;36613:79;;:::i;:::-;36575:119;36725:1;36746:63;36801:7;36792:6;36781:9;36777:22;36746:63;:::i;:::-;36736:73;;36700:115;36493:325;;;;:::o;36820:77::-;36865:7;36890:5;36879:16;;36820:77;;;:::o;36899:78::-;36934:7;36970:4;36963:5;36959:16;36948:27;;36899:78;;;:::o;36979:146::-;37035:9;37064:59;37080:42;37089:32;37115:5;37089:32;:::i;:::-;37080:42;:::i;:::-;37064:59;:::i;:::-;37051:72;;36979:146;;;:::o;37127:135::-;37216:43;37253:5;37216:43;:::i;:::-;37211:3;37204:56;37127:135;;:::o;37264:328::-;37391:4;37425:2;37414:9;37410:18;37402:26;;37434:77;37508:1;37497:9;37493:17;37484:6;37434:77;:::i;:::-;37517:72;37585:2;37574:9;37570:18;37561:6;37517:72;:::i;:::-;37264:328;;;;;:::o;37594:284::-;37656:4;37738:18;37730:6;37727:30;37724:56;;;37760:18;;:::i;:::-;37724:56;37794:29;37816:6;37794:29;:::i;:::-;37786:37;;37870:4;37864;37860:15;37852:23;;37594:284;;;:::o;37880:410::-;37969:5;37990:66;38006:49;38048:6;38006:49;:::i;:::-;37990:66;:::i;:::-;37981:75;;38075:6;38068:5;38061:21;38109:4;38102:5;38098:16;38143:3;38134:6;38129:3;38125:16;38122:25;38119:112;;;38150:79;;:::i;:::-;38119:112;38236:52;38281:6;38276:3;38271;38236:52;:::i;:::-;37975:315;37880:410;;;;;:::o;38302:339::-;38369:5;38414:3;38407:4;38399:6;38395:17;38391:27;38381:122;;38422:79;;:::i;:::-;38381:122;38528:6;38522:13;38549:90;38635:3;38627:6;38620:4;38612:6;38608:17;38549:90;:::i;:::-;38540:99;;38375:266;38302:339;;;;:::o;38643:496::-;38723:6;38768:2;38756:9;38747:7;38743:23;38739:32;38736:119;;;38774:79;;:::i;:::-;38736:119;38907:1;38896:9;38892:17;38886:24;38933:18;38925:6;38922:30;38919:117;;;38955:79;;:::i;:::-;38919:117;39056:74;39122:7;39113:6;39102:9;39098:22;39056:74;:::i;:::-;39046:84;;38861:275;38643:496;;;;:::o;39141:77::-;39186:7;39211:5;39200:16;;39141:77;;;:::o;39220:146::-;39276:9;39305:59;39321:42;39330:32;39356:5;39330:32;:::i;:::-;39321:42;:::i;:::-;39305:59;:::i;:::-;39292:72;;39220:146;;;:::o;39368:135::-;39457:43;39494:5;39457:43;:::i;:::-;39452:3;39445:56;39368:135;;:::o;39505:328::-;39632:4;39666:2;39655:9;39651:18;39643:26;;39675:77;39749:1;39738:9;39734:17;39725:6;39675:77;:::i;:::-;39758:72;39826:2;39815:9;39811:18;39802:6;39758:72;:::i;:::-;39505:328;;;;;:::o;39835:77::-;39880:7;39905:5;39894:16;;39835:77;;;:::o;39914:146::-;39970:9;39999:59;40015:42;40024:32;40050:5;40024:32;:::i;:::-;40015:42;:::i;:::-;39999:59;:::i;:::-;39986:72;;39914:146;;;:::o;40062:135::-;40151:43;40188:5;40151:43;:::i;:::-;40146:3;40139:56;40062:135;;:::o;40199:328::-;40326:4;40360:2;40349:9;40345:18;40337:26;;40369:77;40443:1;40432:9;40428:17;40419:6;40369:77;:::i;:::-;40452:72;40520:2;40509:9;40505:18;40496:6;40452:72;:::i;:::-;40199:328;;;;;:::o;40529:77::-;40574:7;40599:5;40588:16;;40529:77;;;:::o;40608:146::-;40664:9;40693:59;40709:42;40718:32;40744:5;40718:32;:::i;:::-;40709:42;:::i;:::-;40693:59;:::i;:::-;40680:72;;40608:146;;;:::o;40756:135::-;40845:43;40882:5;40845:43;:::i;:::-;40840:3;40833:56;40756:135;;:::o;40893:328::-;41020:4;41054:2;41043:9;41039:18;41031:26;;41063:77;41137:1;41126:9;41122:17;41113:6;41063:77;:::i;:::-;41146:72;41214:2;41203:9;41199:18;41190:6;41146:72;:::i;:::-;40893:328;;;;;:::o;41223:400::-;41359:66;41355:1;41347:6;41343:14;41336:90;41456:66;41451:2;41443:6;41439:15;41432:91;41553:66;41548:2;41540:6;41536:15;41529:91;41223:400;:::o;41625:386::-;41785:3;41802:85;41884:2;41879:3;41802:85;:::i;:::-;41795:92;;41892:93;41981:3;41892:93;:::i;:::-;42006:2;42001:3;41997:12;41990:19;;41625:386;;;:::o;42013:148::-;42149:8;42145:1;42137:6;42133:14;42126:32;42013:148;:::o;42163:384::-;42323:3;42340:84;42422:1;42417:3;42340:84;:::i;:::-;42333:91;;42429:93;42518:3;42429:93;:::i;:::-;42543:1;42538:3;42534:11;42527:18;;42163:384;;;:::o;42549:1255::-;43027:3;43045:148;43189:3;43045:148;:::i;:::-;43038:155;;43206:95;43297:3;43288:6;43206:95;:::i;:::-;43199:102;;43314:95;43405:3;43396:6;43314:95;:::i;:::-;43307:102;;43422:95;43513:3;43504:6;43422:95;:::i;:::-;43415:102;;43530:95;43621:3;43612:6;43530:95;:::i;:::-;43523:102;;43638:148;43782:3;43638:148;:::i;:::-;43631:155;;43799:3;43792:10;;42549:1255;;;;;;;:::o;43806:143::-;43942:3;43938:1;43930:6;43926:14;43919:27;43806:143;:::o;43951:384::-;44111:3;44128:84;44210:1;44205:3;44128:84;:::i;:::-;44121:91;;44217:93;44306:3;44217:93;:::i;:::-;44331:1;44326:3;44322:11;44315:18;;43951:384;;;:::o;44337:681::-;44618:3;44636:95;44727:3;44718:6;44636:95;:::i;:::-;44629:102;;44744:148;44888:3;44744:148;:::i;:::-;44737:155;;44905:95;44996:3;44987:6;44905:95;:::i;:::-;44898:102;;45013:3;45006:10;;44337:681;;;;;:::o;45020:155::-;45059:3;45078:24;45096:5;45078:24;:::i;:::-;45069:33;;45120:4;45113:5;45110:15;45107:41;;45128:18;;:::i;:::-;45107:41;45171:1;45164:5;45160:13;45153:20;;45020:155;;;:::o
Swarm Source
ipfs://ff5ccad0d63612ff77ea26061303a21a2339f9400969477e5ffa3561607bcde0
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.