Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Multichain Info
N/A
Latest 25 from a total of 3,991 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Approval For... | 32531359 | 6 days ago | IN | 0 APE | 0.00252518 | ||||
| Set Approval For... | 32148886 | 16 days ago | IN | 0 APE | 0.00474472 | ||||
| Set Approval For... | 31900965 | 22 days ago | IN | 0 APE | 0.00252518 | ||||
| Set Approval For... | 31900959 | 22 days ago | IN | 0 APE | 0.00251664 | ||||
| Set Approval For... | 31824946 | 24 days ago | IN | 0 APE | 0.00272977 | ||||
| Set Approval For... | 31824942 | 24 days ago | IN | 0 APE | 0.00272977 | ||||
| Set Approval For... | 31824935 | 24 days ago | IN | 0 APE | 0.00475326 | ||||
| Update Pixel Dat... | 31691516 | 27 days ago | IN | 0 APE | 0.01227951 | ||||
| Set Approval For... | 31672494 | 28 days ago | IN | 0 APE | 0.00252518 | ||||
| Set Approval For... | 31672491 | 28 days ago | IN | 0 APE | 0.00251664 | ||||
| Set Approval For... | 31549110 | 30 days ago | IN | 0 APE | 0.00252518 | ||||
| Set Approval For... | 31545639 | 30 days ago | IN | 0 APE | 0.00252518 | ||||
| Withdraw Tokens | 31004879 | 40 days ago | IN | 0 APE | 0.00376744 | ||||
| Set Approval For... | 30635165 | 46 days ago | IN | 0 APE | 0.00475326 | ||||
| Set Approval For... | 30398059 | 49 days ago | IN | 0 APE | 0.00118869 | ||||
| Set Approval For... | 30071072 | 51 days ago | IN | 0 APE | 0.00118869 | ||||
| Set Approval For... | 28963032 | 61 days ago | IN | 0 APE | 0.00118656 | ||||
| Set Approval For... | 26312039 | 79 days ago | IN | 0 APE | 0.00118656 | ||||
| Set Approval For... | 26174661 | 81 days ago | IN | 0 APE | 0.00118869 | ||||
| Set Approval For... | 25577710 | 89 days ago | IN | 0 APE | 0.00118869 | ||||
| Set Approval For... | 25455769 | 92 days ago | IN | 0 APE | 0.00118869 | ||||
| Set Approval For... | 25442003 | 92 days ago | IN | 0 APE | 0.00118869 | ||||
| Set Approval For... | 25438736 | 92 days ago | IN | 0 APE | 0.00118656 | ||||
| Set Approval For... | 25354686 | 94 days ago | IN | 0 APE | 0.00118656 | ||||
| Set Approval For... | 25160784 | 98 days ago | IN | 0 APE | 0.00062954 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ProjectNineNFT
Compiler Version
v0.8.26+commit.8a97fa7a
Contract Source Code (Solidity)
/**
*Submitted for verification at apescan.io on 2025-03-17
*/
/**
* ██████╗ ██████╗ ██████╗ ██╗███████╗ ██████╗████████╗ █████╗
* ██╔══██╗██╔══██╗██╔═══██╗ ██║██╔════╝██╔════╝╚══██╔══╝ ██╔══██╗
* ██████╔╝██████╔╝██║ ██║ ██║█████╗ ██║ ██║ ╚██████║
* ██╔═══╝ ██╔══██╗██║ ██║██ ██║██╔══╝ ██║ ██║ ╚═══██║
* ██║ ██║ ██║╚██████╔╝╚█████╔╝███████╗╚██████╗ ██║ █████╔╝
* ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚════╝
* On-chain Project-9 OnChain NFT, by SoftWave.
**/
// File: @openzeppelin/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: @openzeppelin/contracts/token/ERC721/IERC721.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
/**
* @dev Required interface of an ERC-721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC-721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}
// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC-721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
// File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
// File: @openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/utils/ERC721Utils.sol)
pragma solidity ^0.8.20;
/**
* @dev Library that provide common ERC-721 utility functions.
*
* See https://eips.ethereum.org/EIPS/eip-721[ERC-721].
*
* _Available since v5.1._
*/
library ERC721Utils {
/**
* @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received}
* on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
*
* The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
* Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept
* the transfer.
*/
function checkOnERC721Received(
address operator,
address from,
address to,
uint256 tokenId,
bytes memory data
) internal {
if (to.code.length > 0) {
try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
// Token rejected
revert IERC721Errors.ERC721InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
// non-IERC721Receiver implementer
revert IERC721Errors.ERC721InvalidReceiver(to);
} else {
assembly ("memory-safe") {
revert(add(32, reason), mload(reason))
}
}
}
}
}
}
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// File: @openzeppelin/contracts/utils/Panic.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* // Use any of the declared internal constants
* function foo() { Panic.GENERIC.panic(); }
*
* // Alternatively
* function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
*
* _Available since v5.1._
*/
// slither-disable-next-line unused-state
library Panic {
/// @dev generic / unspecified error
uint256 internal constant GENERIC = 0x00;
/// @dev used by the assert() builtin
uint256 internal constant ASSERT = 0x01;
/// @dev arithmetic underflow or overflow
uint256 internal constant UNDER_OVERFLOW = 0x11;
/// @dev division or modulo by zero
uint256 internal constant DIVISION_BY_ZERO = 0x12;
/// @dev enum conversion error
uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
/// @dev invalid encoding in storage
uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
/// @dev empty array pop
uint256 internal constant EMPTY_ARRAY_POP = 0x31;
/// @dev array out of bounds access
uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
/// @dev resource error (too large allocation or too large array)
uint256 internal constant RESOURCE_ERROR = 0x41;
/// @dev calling invalid internal function
uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
/// @dev Reverts with a panic code. Recommended to use with
/// the internal constants with predefined codes.
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}
// File: @openzeppelin/contracts/utils/math/SafeCast.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}
// File: @openzeppelin/contracts/utils/math/Math.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2²⁵⁶ + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= prod1) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
uint256 exp;
unchecked {
exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);
value >>= exp;
result += exp;
exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);
value >>= exp;
result += exp;
exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);
value >>= exp;
result += exp;
exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);
value >>= exp;
result += exp;
exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);
value >>= exp;
result += exp;
exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);
value >>= exp;
result += exp;
exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);
value >>= exp;
result += exp;
result += SafeCast.toUint(value > 1);
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
uint256 isGt;
unchecked {
isGt = SafeCast.toUint(value > (1 << 128) - 1);
value >>= isGt * 128;
result += isGt * 16;
isGt = SafeCast.toUint(value > (1 << 64) - 1);
value >>= isGt * 64;
result += isGt * 8;
isGt = SafeCast.toUint(value > (1 << 32) - 1);
value >>= isGt * 32;
result += isGt * 4;
isGt = SafeCast.toUint(value > (1 << 16) - 1);
value >>= isGt * 16;
result += isGt * 2;
result += SafeCast.toUint(value > (1 << 8) - 1);
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}
// File: @openzeppelin/contracts/utils/math/SignedMath.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
}
}
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
// Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
// taking advantage of the most significant (or "sign" bit) in two's complement representation.
// This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
// the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
int256 mask = n >> 255;
// A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
return uint256((n + mask) ^ mask);
}
}
}
// File: @openzeppelin/contracts/utils/Strings.sol
// OpenZeppelin Contracts (last updated v5.2.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
/**
* @dev String operations.
*/
library Strings {
using SafeCast for *;
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev The string being parsed contains characters that are not in scope of the given base.
*/
error StringsInvalidChar();
/**
* @dev The string being parsed is not a properly formatted address.
*/
error StringsInvalidAddressFormat();
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly ("memory-safe") {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly ("memory-safe") {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
* representation, according to EIP-55.
*/
function toChecksumHexString(address addr) internal pure returns (string memory) {
bytes memory buffer = bytes(toHexString(addr));
// hash the hex part of buffer (skip length + 2 bytes, length 40)
uint256 hashValue;
assembly ("memory-safe") {
hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
}
for (uint256 i = 41; i > 1; --i) {
// possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
// case shift by xoring with 0x20
buffer[i] ^= 0x20;
}
hashValue >>= 4;
}
return string(buffer);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
/**
* @dev Parse a decimal string and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input) internal pure returns (uint256) {
return parseUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
uint256 result = 0;
for (uint256 i = begin; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 9) return (false, 0);
result *= 10;
result += chr;
}
return (true, result);
}
/**
* @dev Parse a decimal string and returns the value as a `int256`.
*
* Requirements:
* - The string must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input) internal pure returns (int256) {
return parseInt(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {
(bool success, int256 value) = tryParseInt(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
* the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {
return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
}
uint256 private constant ABS_MIN_INT256 = 2 ** 255;
/**
* @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character or if the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, int256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseIntUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseIntUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, int256 value) {
bytes memory buffer = bytes(input);
// Check presence of a negative sign.
bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
bool positiveSign = sign == bytes1("+");
bool negativeSign = sign == bytes1("-");
uint256 offset = (positiveSign || negativeSign).toUint();
(bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);
if (absSuccess && absValue < ABS_MIN_INT256) {
return (true, negativeSign ? -int256(absValue) : int256(absValue));
} else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
return (true, type(int256).min);
} else return (false, 0);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input) internal pure returns (uint256) {
return parseHexUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseHexUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
* invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseHexUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseHexUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
// skip 0x prefix if present
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 offset = hasPrefix.toUint() * 2;
uint256 result = 0;
for (uint256 i = begin + offset; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 15) return (false, 0);
result *= 16;
unchecked {
// Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
// This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked.
result += chr;
}
}
return (true, result);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input) internal pure returns (address) {
return parseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {
(bool success, address value) = tryParseAddress(input, begin, end);
if (!success) revert StringsInvalidAddressFormat();
return value;
}
/**
* @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
* formatted address. See {parseAddress} requirements.
*/
function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
return tryParseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
* formatted address. See {parseAddress} requirements.
*/
function tryParseAddress(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, address value) {
if (end > bytes(input).length || begin > end) return (false, address(0));
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 expectedLength = 40 + hasPrefix.toUint() * 2;
// check that input is the correct length
if (end - begin == expectedLength) {
// length guarantees that this does not overflow, and value is at most type(uint160).max
(bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);
return (s, address(uint160(v)));
} else {
return (false, address(0));
}
}
function _tryParseChr(bytes1 chr) private pure returns (uint8) {
uint8 value = uint8(chr);
// Try to parse `chr`:
// - Case 1: [0-9]
// - Case 2: [a-f]
// - Case 3: [A-F]
// - otherwise not supported
unchecked {
if (value > 47 && value < 58) value -= 48;
else if (value > 96 && value < 103) value -= 87;
else if (value > 64 && value < 71) value -= 55;
else return type(uint8).max;
}
return value;
}
/**
* @dev Reads a bytes32 from a bytes array without bounds checking.
*
* NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
* assembly block as such would prevent some optimizations.
*/
function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
// This is not memory safe in the general case, but all calls to this private function are within bounds.
assembly ("memory-safe") {
value := mload(add(buffer, add(0x20, offset)))
}
}
}
// File: @openzeppelin/contracts/utils/introspection/ERC165.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
// File: @openzeppelin/contracts/token/ERC721/ERC721.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
mapping(uint256 tokenId => address) private _owners;
mapping(address owner => uint256) private _balances;
mapping(uint256 tokenId => address) private _tokenApprovals;
mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual returns (uint256) {
if (owner == address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual returns (address) {
return _requireOwned(tokenId);
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
_requireOwned(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual {
_approve(to, tokenId, _msgSender());
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual returns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
transferFrom(from, to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*
* IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
* core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances
* consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
* `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
*/
function _getApproved(uint256 tokenId) internal view virtual returns (address) {
return _tokenApprovals[tokenId];
}
/**
* @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
return
spender != address(0) &&
(owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
/**
* @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
* Reverts if:
* - `spender` does not have approval from `owner` for `tokenId`.
* - `spender` does not have approval to manage all of `owner`'s assets.
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
* a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
*
* WARNING: Increasing an account's balance using this function tends to be paired with an override of the
* {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
* remain consistent with one another.
*/
function _increaseBalance(address account, uint128 value) internal virtual {
unchecked {
_balances[account] += value;
}
}
/**
* @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
* (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that
* `auth` is either the owner of the token, or approved to operate on the token (by the owner).
*
* Emits a {Transfer} event.
*
* NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
address from = _ownerOf(tokenId);
// Perform (optional) operator check
if (auth != address(0)) {
_checkAuthorized(from, auth, tokenId);
}
// Execute the update
if (from != address(0)) {
// Clear approval. No need to re-authorize or emit the Approval event
_approve(address(0), tokenId, address(0), false);
unchecked {
_balances[from] -= 1;
}
}
if (to != address(0)) {
unchecked {
_balances[to] += 1;
}
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
return from;
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner != address(0)) {
revert ERC721InvalidSender(address(0));
}
}
/**
* @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal {
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
* are aware of the ERC-721 standard to prevent tokens from being forever locked.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is like {safeTransferFrom} in the sense that it invokes
* {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `tokenId` token must exist and be owned by `from`.
* - `to` cannot be the zero address.
* - `from` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId) internal {
_safeTransfer(from, to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
* either the owner of the token, or approved to operate on all tokens held by this owner.
*
* Emits an {Approval} event.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address to, uint256 tokenId, address auth) internal {
_approve(to, tokenId, auth, true);
}
/**
* @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
* emitted in the context of transfers.
*/
function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
// Avoid reading the owner unless necessary
if (emitEvent || auth != address(0)) {
address owner = _requireOwned(tokenId);
// We do not use _isAuthorized because single-token approvals should not be able to call approve
if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
_tokenApprovals[tokenId] = to;
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Requirements:
* - operator can't be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC721InvalidOperator(operator);
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
* Returns the owner.
*
* Overrides to ownership logic should be done to {_ownerOf}.
*/
function _requireOwned(uint256 tokenId) internal view returns (address) {
address owner = _ownerOf(tokenId);
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
}
// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Enumerable.sol)
pragma solidity ^0.8.20;
/**
* @dev This implements an optional extension of {ERC721} defined in the ERC that adds enumerability
* of all the token ids in the contract as well as all token ids owned by each account.
*
* CAUTION: {ERC721} extensions that implement custom `balanceOf` logic, such as {ERC721Consecutive},
* interfere with enumerability and should not be used together with {ERC721Enumerable}.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens;
mapping(uint256 tokenId => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 tokenId => uint256) private _allTokensIndex;
/**
* @dev An `owner`'s token query was out of bounds for `index`.
*
* NOTE: The owner being `address(0)` indicates a global out of bounds index.
*/
error ERC721OutOfBoundsIndex(address owner, uint256 index);
/**
* @dev Batch mint is not allowed.
*/
error ERC721EnumerableForbiddenBatchMint();
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
if (index >= balanceOf(owner)) {
revert ERC721OutOfBoundsIndex(owner, index);
}
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual returns (uint256) {
if (index >= totalSupply()) {
revert ERC721OutOfBoundsIndex(address(0), index);
}
return _allTokens[index];
}
/**
* @dev See {ERC721-_update}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
address previousOwner = super._update(to, tokenId, auth);
if (previousOwner == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_removeTokenFromOwnerEnumeration(previousOwner, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_addTokenToOwnerEnumeration(to, tokenId);
}
return previousOwner;
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = balanceOf(to) - 1;
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = balanceOf(from);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
mapping(uint256 index => uint256) storage _ownedTokensByOwner = _ownedTokens[from];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokensByOwner[lastTokenIndex];
_ownedTokensByOwner[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokensByOwner[lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
/**
* See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
*/
function _increaseBalance(address account, uint128 amount) internal virtual override {
if (amount > 0) {
revert ERC721EnumerableForbiddenBatchMint();
}
super._increaseBalance(account, amount);
}
}
// File: @openzeppelin/contracts/access/Ownable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File: @openzeppelin/contracts/utils/Base64.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Base64.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides a set of functions to operate with Base64 strings.
*/
library Base64 {
/**
* @dev Base64 Encoding/Decoding Table
* See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648
*/
string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
string internal constant _TABLE_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
/**
* @dev Converts a `bytes` to its Bytes64 `string` representation.
*/
function encode(bytes memory data) internal pure returns (string memory) {
return _encode(data, _TABLE, true);
}
/**
* @dev Converts a `bytes` to its Bytes64Url `string` representation.
* Output is not padded with `=` as specified in https://www.rfc-editor.org/rfc/rfc4648[rfc4648].
*/
function encodeURL(bytes memory data) internal pure returns (string memory) {
return _encode(data, _TABLE_URL, false);
}
/**
* @dev Internal table-agnostic conversion
*/
function _encode(bytes memory data, string memory table, bool withPadding) private pure returns (string memory) {
/**
* Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
* https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
*/
if (data.length == 0) return "";
// If padding is enabled, the final length should be `bytes` data length divided by 3 rounded up and then
// multiplied by 4 so that it leaves room for padding the last chunk
// - `data.length + 2` -> Prepare for division rounding up
// - `/ 3` -> Number of 3-bytes chunks (rounded up)
// - `4 *` -> 4 characters for each chunk
// This is equivalent to: 4 * Math.ceil(data.length / 3)
//
// If padding is disabled, the final length should be `bytes` data length multiplied by 4/3 rounded up as
// opposed to when padding is required to fill the last chunk.
// - `4 * data.length` -> 4 characters for each chunk
// - ` + 2` -> Prepare for division rounding up
// - `/ 3` -> Number of 3-bytes chunks (rounded up)
// This is equivalent to: Math.ceil((4 * data.length) / 3)
uint256 resultLength = withPadding ? 4 * ((data.length + 2) / 3) : (4 * data.length + 2) / 3;
string memory result = new string(resultLength);
assembly ("memory-safe") {
// Prepare the lookup table (skip the first "length" byte)
let tablePtr := add(table, 1)
// Prepare result pointer, jump over length
let resultPtr := add(result, 0x20)
let dataPtr := data
let endPtr := add(data, mload(data))
// In some cases, the last iteration will read bytes after the end of the data. We cache the value, and
// set it to zero to make sure no dirty bytes are read in that section.
let afterPtr := add(endPtr, 0x20)
let afterCache := mload(afterPtr)
mstore(afterPtr, 0x00)
// Run over the input, 3 bytes at a time
for {
} lt(dataPtr, endPtr) {
} {
// Advance 3 bytes
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)
// To write each character, shift the 3 byte (24 bits) chunk
// 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
// and apply logical AND with 0x3F to bitmask the least significant 6 bits.
// Use this as an index into the lookup table, mload an entire word
// so the desired character is in the least significant byte, and
// mstore8 this least significant byte into the result and continue.
mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
}
// Reset the value that was cached
mstore(afterPtr, afterCache)
if withPadding {
// When data `bytes` is not exactly 3 bytes long
// it is padded with `=` characters at the end
switch mod(mload(data), 3)
case 1 {
mstore8(sub(resultPtr, 1), 0x3d)
mstore8(sub(resultPtr, 2), 0x3d)
}
case 2 {
mstore8(sub(resultPtr, 1), 0x3d)
}
}
}
return result;
}
}
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
// File: contracts/ProjectNineData.sol
/**
* ██████╗ ██████╗ ██████╗ ██╗███████╗ ██████╗████████╗ █████╗
* ██╔══██╗██╔══██╗██╔═══██╗ ██║██╔════╝██╔════╝╚══██╔══╝ ██╔══██╗
* ██████╔╝██████╔╝██║ ██║ ██║█████╗ ██║ ██║ ╚██████║
* ██╔═══╝ ██╔══██╗██║ ██║██ ██║██╔══╝ ██║ ██║ ╚═══██║
* ██║ ██║ ██║╚██████╔╝╚█████╔╝███████╗╚██████╗ ██║ █████╔╝
* ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚════╝
* On-chain Project-9 OnChain Data, by SoftWave.
**/
pragma solidity ^0.8.0;
contract ProjectNineData {
address payable internal deployer;
address payable public nftContract;
bool private contractLocked = false;
uint256 private constant CANVAS_SIZE = 24;
uint256 private constant PIXEL_DATA_SIZE = CANVAS_SIZE * CANVAS_SIZE * 3;
uint256 public constant MAX_LIMIT = 2222;
Coordination public updateCoord;
struct Trait {
string traitType;
string value;
}
struct Coordination {
uint256 startX;
uint256 startY;
uint256 width;
uint256 height;
}
struct NineData {
bytes pixelData;
Trait[] traits;
bytes equippedWeapon;
uint256 xp;
}
mapping(uint256 => NineData) private nineData;
modifier onlyNFTContract() {
require(msg.sender == nftContract, "Only NFTContract.");
_;
}
modifier onlyDeployer() {
require(msg.sender == deployer, "Only deployer.");
_;
}
modifier unlocked() {
require(!contractLocked, "Contract is locked.");
_;
}
constructor() {
deployer = payable(msg.sender);
}
function setNFTContract(address contractAddress) external onlyDeployer {
nftContract = payable(contractAddress);
}
function setUpdateCoordination(
uint256 startX,
uint256 startY,
uint256 width,
uint256 height
) external onlyDeployer {
require(startX + width <= CANVAS_SIZE, "Width out of bounds");
require(startY + height <= CANVAS_SIZE, "Height out of bounds");
updateCoord = Coordination(startX, startY, width, height);
}
function lockContract() external onlyDeployer unlocked {
contractLocked = true;
}
function storePixelData(uint256 tokenId, bytes memory pixelData)
external
onlyDeployer
unlocked
{
require(tokenId < MAX_LIMIT, "Invalid tokenId");
require(
pixelData.length == PIXEL_DATA_SIZE,
"Invalid pixel data length"
);
nineData[tokenId].pixelData = pixelData;
}
function batchStorePixelData(
uint256[] memory tokenIds,
bytes[] memory pixelDataArray
) external onlyDeployer unlocked {
require(tokenIds.length == pixelDataArray.length, "Mismatched arrays");
for (uint256 i = 0; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
bytes memory pixelData = pixelDataArray[i];
require(tokenId < MAX_LIMIT, "Invalid tokenId");
require(
pixelData.length == PIXEL_DATA_SIZE,
"Invalid pixel data length"
);
nineData[tokenId].pixelData = pixelData;
}
}
function storeTraits(uint256 tokenId, Trait[] memory traits)
external
onlyDeployer
unlocked
{
require(traits.length > 0, "Traits cannot be empty");
delete nineData[tokenId].traits;
for (uint256 i = 0; i < traits.length; i++) {
nineData[tokenId].traits.push(traits[i]);
}
}
function batchStoreTraits(
uint256[] memory tokenIds,
Trait[][] memory traitsArray
) external onlyDeployer unlocked {
require(tokenIds.length == traitsArray.length, "Mismatched arrays");
for (uint256 i = 0; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
Trait[] memory traits = traitsArray[i];
delete nineData[tokenId].traits;
for (uint256 j = 0; j < traits.length; j++) {
nineData[tokenId].traits.push(traits[j]);
}
}
}
function getTraits(uint256 tokenId) external view returns (string memory) {
require(nineData[tokenId].traits.length > 0, "Traits not set");
bytes memory jsonTraits = "[";
for (uint256 i = 0; i < nineData[tokenId].traits.length; i++) {
jsonTraits = abi.encodePacked(
jsonTraits,
'{"trait_type":"',
nineData[tokenId].traits[i].traitType,
'","value":"',
nineData[tokenId].traits[i].value,
'"}'
);
if (i < nineData[tokenId].traits.length - 1) {
jsonTraits = abi.encodePacked(jsonTraits, ",");
}
}
// Append XP
if (nineData[tokenId].traits.length > 0) {
jsonTraits = abi.encodePacked(jsonTraits, ",");
}
jsonTraits = abi.encodePacked(
jsonTraits,
'{"trait_type":"XP","value":"',
Strings.toString(nineData[tokenId].xp),
'"}'
);
// Append hasWeapon
bool hasWeapon = nineData[tokenId].equippedWeapon.length > 0;
jsonTraits = abi.encodePacked(
jsonTraits,
',{"trait_type":"hasWeapon","value":"',
hasWeapon ? "yes" : "no",
'"}]'
);
return string(jsonTraits);
}
function getNineData(uint256 tokenId) external view returns (bytes memory) {
require(tokenId < MAX_LIMIT, "Invalid tokenId");
require(
nineData[tokenId].pixelData.length == PIXEL_DATA_SIZE,
"Pixel data not set"
);
return nineData[tokenId].pixelData;
}
function updateWeapon(uint256 tokenId, bytes memory newWeapon)
external
onlyNFTContract
{
uint256 area = updateCoord.width * updateCoord.height;
require(
newWeapon.length == area * 3,
"newWeapon array length mismatch"
);
nineData[tokenId].equippedWeapon = newWeapon;
if (nineData[tokenId].xp < 3) nineData[tokenId].xp += 1;
}
function updateTrait(
uint256 tokenId,
string memory traitType,
string memory value
) external onlyNFTContract {
Trait[] storage traits = nineData[tokenId].traits;
for (uint256 i = 0; i < traits.length; i++) {
if (
keccak256(bytes(traits[i].traitType)) ==
keccak256(bytes(traitType))
) {
traits[i].value = value;
return;
}
}
traits.push(Trait(traitType, value));
}
function getEquippedWeapon(uint256 tokenId)
external
view
returns (bytes memory)
{
return nineData[tokenId].equippedWeapon;
}
function train(uint256 tokenId) external onlyNFTContract {
if (nineData[tokenId].xp < 3) nineData[tokenId].xp += 1;
}
function exercise(uint256 tokenId) external onlyNFTContract {
if (nineData[tokenId].xp < 3) nineData[tokenId].xp += 1;
}
function getXP(uint256 tokenId) external view returns (uint256) {
return nineData[tokenId].xp;
}
}
// File: contracts/ProjectNineNFT.sol
pragma solidity ^0.8.0;
contract ProjectNineNFT is ERC721Enumerable, Ownable {
ProjectNineData public dataContract;
uint256 public immutable MAX_SUPPLY = 2222;
uint256 public constant BASE_MAX_PER_WALLET = 3;
uint256 public remaining;
address payable public deployer;
string private baseURI;
string private externalURI;
bool public unlimitedMintEnabled = false;
mapping(address => bool) private WLAccounts;
mapping(address => uint256) public mintCounts;
uint256 private immutable seed;
IERC20 public paymentToken;
uint256 public mintPrice;
uint256 public craftPrice;
constructor(address dataContractAddress, address payable _deployer)
ERC721("ProjectNine", "PNINE")
Ownable(_deployer)
{
dataContract = ProjectNineData(dataContractAddress);
deployer = _deployer;
remaining = MAX_SUPPLY;
seed = uint256(
keccak256(
abi.encodePacked(blockhash(block.number - 1), address(this))
)
);
}
modifier onlyDeployer() {
require(msg.sender == deployer, "Only Deployer.");
_;
}
function setPaymentToken(address tokenAddress) external onlyDeployer {
paymentToken = IERC20(tokenAddress);
}
function setPrices(uint256 _mintPrice, uint256 _craftPrice)
external
onlyDeployer
{
mintPrice = _mintPrice;
craftPrice = _craftPrice;
}
function setBaseUri(string memory uri, string memory _externalUri)
external
onlyDeployer
{
baseURI = uri;
externalURI = _externalUri;
}
function setWLAccounts(address[] memory participants)
external
onlyDeployer
{
for (uint256 i = 0; i < participants.length; i++) {
WLAccounts[participants[i]] = true;
}
}
function isInWhitelist(address participant) public view returns (bool) {
return WLAccounts[participant];
}
function mint() external {
require(totalSupply() < MAX_SUPPLY, "Max supply reached");
require(mintPrice > 0, "Minting not enabled");
// Check mint limits
if (!unlimitedMintEnabled) {
uint256 maxAllowed = BASE_MAX_PER_WALLET;
if (isInWhitelist(msg.sender)) {
maxAllowed += 2;
}
require(mintCounts[msg.sender] < maxAllowed, "Exceeds mint limit");
}
// Process payment
require(
paymentToken.transferFrom(msg.sender, address(this), mintPrice),
"Payment failed"
);
uint256 tokenId = _getRandomTokenId();
_safeMint(msg.sender, tokenId);
mintCounts[msg.sender]++;
}
function mintBatch(uint256 count) external {
require(count > 0, "Count must be > 0");
require(totalSupply() + count <= MAX_SUPPLY, "Exceeds max supply");
// Check mint limits unless unlimited minting is enabled
if (!unlimitedMintEnabled) {
uint256 maxAllowed = BASE_MAX_PER_WALLET;
if (isInWhitelist(msg.sender)) {
maxAllowed += 2;
}
require(
mintCounts[msg.sender] + count <= maxAllowed,
"Exceeds mint limit"
);
}
// Process payment for the total batch.
uint256 totalPrice = mintPrice * count;
require(
paymentToken.transferFrom(msg.sender, address(this), totalPrice),
"Payment failed"
);
// Mint each token in the batch.
for (uint256 i = 0; i < count; i++) {
uint256 tokenId = _getRandomTokenId();
_safeMint(msg.sender, tokenId);
if (!unlimitedMintEnabled) {
mintCounts[msg.sender]++;
}
}
}
function _getRandomTokenId() private returns (uint256) {
require(remaining > 0, "All minted");
uint256 index = MAX_SUPPLY - remaining;
uint256 tokenId = _permute(index);
remaining--;
return tokenId;
}
function tokenURI(uint256 tokenId)
public
view
override
returns (string memory)
{
require(tokenId < MAX_SUPPLY, "Token does not exist");
// Construct the external image URL and interactive URL
string memory imageUrl = string(
abi.encodePacked(baseURI, "/api/image/", toString(tokenId))
);
string memory externalUrl = string(
abi.encodePacked(externalURI, "/token/", toString(tokenId))
);
string memory iFrameUrl = string(
abi.encodePacked(baseURI, "/token/", toString(tokenId))
);
string memory traits = dataContract.getTraits(tokenId);
return
string(
abi.encodePacked(
"data:application/json;base64,",
Base64.encode(
bytes(
abi.encodePacked(
'{"name":"P9 #',
toString(tokenId),
'", "description":"Project 9 - saving endangered creatures in uncharted realms.",',
'"image":"',
imageUrl,
'", "animation_url":"',
iFrameUrl,
'", "iframe_url":"',
iFrameUrl,
'", "external_url":"',
externalUrl,
'", "attributes":',
traits,
"}"
)
)
)
)
);
}
function updatePixelData(uint256 tokenId, bytes memory newPixelData)
external
{
require(ownerOf(tokenId) == msg.sender, "Not token owner");
require(
paymentToken.transferFrom(msg.sender, address(this), craftPrice),
"Payment failed"
);
dataContract.updateWeapon(tokenId, newPixelData);
}
function train(uint256 tokenId) external {
require(ownerOf(tokenId) == msg.sender, "Not token owner");
dataContract.train(tokenId);
}
function exercise(uint256 tokenId) external {
require(ownerOf(tokenId) == msg.sender, "Not token owner");
dataContract.exercise(tokenId);
}
function setUnlimitedMinting(bool value) external onlyDeployer {
unlimitedMintEnabled = value;
}
function _permute(uint256 index) internal view returns (uint256) {
uint256 prime = 2221;
uint256 a = (seed % (prime - 1)) + 1;
return (a * index) % prime;
}
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) return "0";
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
// Withdraw funds function
function withdrawTokens(IERC20 token) external onlyDeployer {
require(address(token) != address(0), "Invalid token");
token.transfer(deployer, token.balanceOf(address(this)));
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"dataContractAddress","type":"address"},{"internalType":"address payable","name":"_deployer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BASE_MAX_PER_WALLET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"craftPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dataContract","outputs":[{"internalType":"contract ProjectNineData","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deployer","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"exercise","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"}],"name":"isInWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"mintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"remaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"},{"internalType":"string","name":"_externalUri","type":"string"}],"name":"setBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"setPaymentToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintPrice","type":"uint256"},{"internalType":"uint256","name":"_craftPrice","type":"uint256"}],"name":"setPrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"setUnlimitedMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"participants","type":"address[]"}],"name":"setWLAccounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"train","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlimitedMintEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"newPixelData","type":"bytes"}],"name":"updatePixelData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c06040526108ae6080908152505f60105f6101000a81548160ff021916908315150217905550348015610031575f80fd5b506040516159703803806159708339818101604052810190610053919061038c565b806040518060400160405280600b81526020017f50726f6a6563744e696e650000000000000000000000000000000000000000008152506040518060400160405280600581526020017f504e494e45000000000000000000000000000000000000000000000000000000815250815f90816100ce9190610604565b5080600190816100de9190610604565b5050505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610151575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161014891906106e2565b60405180910390fd5b6101608161023060201b60201c565b5081600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600d5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550608051600c819055506001436101f79190610728565b403060405160200161020a9291906107c9565b604051602081830303815290604052805190602001205f1c60a0818152505050506107f4565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610320826102f7565b9050919050565b61033081610316565b811461033a575f80fd5b50565b5f8151905061034b81610327565b92915050565b5f61035b826102f7565b9050919050565b61036b81610351565b8114610375575f80fd5b50565b5f8151905061038681610362565b92915050565b5f80604083850312156103a2576103a16102f3565b5b5f6103af8582860161033d565b92505060206103c085828601610378565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061044557607f821691505b60208210810361045857610457610401565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026104ba7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261047f565b6104c4868361047f565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6105086105036104fe846104dc565b6104e5565b6104dc565b9050919050565b5f819050919050565b610521836104ee565b61053561052d8261050f565b84845461048b565b825550505050565b5f90565b61054961053d565b610554818484610518565b505050565b5b818110156105775761056c5f82610541565b60018101905061055a565b5050565b601f8211156105bc5761058d8161045e565b61059684610470565b810160208510156105a5578190505b6105b96105b185610470565b830182610559565b50505b505050565b5f82821c905092915050565b5f6105dc5f19846008026105c1565b1980831691505092915050565b5f6105f483836105cd565b9150826002028217905092915050565b61060d826103ca565b67ffffffffffffffff811115610626576106256103d4565b5b610630825461042e565b61063b82828561057b565b5f60209050601f83116001811461066c575f841561065a578287015190505b61066485826105e9565b8655506106cb565b601f19841661067a8661045e565b5f5b828110156106a15784890151825560018201915060208501945060208101905061067c565b868310156106be57848901516106ba601f8916826105cd565b8355505b6001600288020188555050505b505050505050565b6106dc81610316565b82525050565b5f6020820190506106f55f8301846106d3565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610732826104dc565b915061073d836104dc565b9250828203905081811115610755576107546106fb565b5b92915050565b5f819050919050565b5f819050919050565b61077e6107798261075b565b610764565b82525050565b5f8160601b9050919050565b5f61079a82610784565b9050919050565b5f6107ab82610790565b9050919050565b6107c36107be82610316565b6107a1565b82525050565b5f6107d4828561076d565b6020820191506107e482846107b2565b6014820191508190509392505050565b60805160a05161513f6108315f395f612c7801525f81816109e201528181610ed10152818161135701528181611d65015261228d015261513f5ff3fe608060405234801561000f575f80fd5b5060043610610251575f3560e01c80634f6ccce71161014457806380796bbf116100c1578063b07f0a4111610085578063b07f0a41146106bd578063b88d4fde146106d9578063c87b56dd146106f5578063d5f3948814610725578063e985e9c514610743578063f2fde38b1461077357610251565b806380796bbf1461062b5780638099b002146106475780638da5cb5b1461066557806395d89b4114610683578063a22cb465146106a157610251565b806367b06aee1161010857806367b06aee1461059b5780636817c76c146105b75780636a326ab1146105d557806370a08231146105f1578063715018a61461062157610251565b80634f6ccce7146104cf57806353277879146104ff57806355234ec01461052f578063584430e61461054d5780636352211e1461056b57610251565b80632061cea7116101d257806332cb6b0c1161019657806332cb6b0c14610441578063368004ed1461045f5780633a87d2851461047b57806342842e0e1461049757806349df728c146104b357610251565b80632061cea71461039f57806320e409b4146103bb57806323b872dd146103d75780632f745c59146103f35780633013ce291461042357610251565b806309fd82121161021957806309fd82121461030b5780630d6688181461033b5780631249c58b1461035957806315f04ccd1461036357806318160ddd1461038157610251565b806301ffc9a71461025557806305fefda71461028557806306fdde03146102a1578063081812fc146102bf578063095ea7b3146102ef575b5f80fd5b61026f600480360381019061026a91906135c5565b61078f565b60405161027c919061360a565b60405180910390f35b61029f600480360381019061029a9190613656565b610808565b005b6102a96108a9565b6040516102b69190613704565b60405180910390f35b6102d960048036038101906102d49190613724565b610938565b6040516102e6919061378e565b60405180910390f35b610309600480360381019061030491906137d1565b610953565b005b6103256004803603810190610320919061380f565b610969565b604051610332919061360a565b60405180910390f35b6103436109bb565b6040516103509190613895565b60405180910390f35b6103616109e0565b005b61036b610c8d565b604051610378919061360a565b60405180910390f35b610389610c9f565b60405161039691906138bd565b60405180910390f35b6103b960048036038101906103b49190613a02565b610cab565b005b6103d560048036038101906103d09190613724565b610e8d565b005b6103f160048036038101906103ec9190613a5c565b61118d565b005b61040d600480360381019061040891906137d1565b61128c565b60405161041a91906138bd565b60405180910390f35b61042b611330565b6040516104389190613acc565b60405180910390f35b610449611355565b60405161045691906138bd565b60405180910390f35b61047960048036038101906104749190613724565b611379565b005b61049560048036038101906104909190613b0f565b611479565b005b6104b160048036038101906104ac9190613a5c565b611524565b005b6104cd60048036038101906104c89190613b75565b611543565b005b6104e960048036038101906104e49190613724565b611757565b6040516104f691906138bd565b60405180910390f35b6105196004803603810190610514919061380f565b6117c9565b60405161052691906138bd565b60405180910390f35b6105376117de565b60405161054491906138bd565b60405180910390f35b6105556117e4565b60405161056291906138bd565b60405180910390f35b61058560048036038101906105809190613724565b6117ea565b604051610592919061378e565b60405180910390f35b6105b560048036038101906105b09190613c64565b6117fb565b005b6105bf611915565b6040516105cc91906138bd565b60405180910390f35b6105ef60048036038101906105ea919061380f565b61191b565b005b61060b6004803603810190610606919061380f565b6119ed565b60405161061891906138bd565b60405180910390f35b610629611aa3565b005b61064560048036038101906106409190613d49565b611ab6565b005b61064f611b69565b60405161065c91906138bd565b60405180910390f35b61066d611b6e565b60405161067a919061378e565b60405180910390f35b61068b611b96565b6040516106989190613704565b60405180910390f35b6106bb60048036038101906106b69190613dbf565b611c26565b005b6106d760048036038101906106d29190613724565b611c3c565b005b6106f360048036038101906106ee9190613dfd565b611d3c565b005b61070f600480360381019061070a9190613724565b611d61565b60405161071c9190613704565b60405180910390f35b61072d611f52565b60405161073a9190613e9d565b60405180910390f35b61075d60048036038101906107589190613eb6565b611f77565b60405161076a919061360a565b60405180910390f35b61078d6004803603810190610788919061380f565b612005565b005b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610801575061080082612089565b5b9050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088e90613f3e565b60405180910390fd5b81601481905550806015819055505050565b60605f80546108b790613f89565b80601f01602080910402602001604051908101604052809291908181526020018280546108e390613f89565b801561092e5780601f106109055761010080835404028352916020019161092e565b820191905f5260205f20905b81548152906001019060200180831161091157829003601f168201915b5050505050905090565b5f6109428261216a565b5061094c826121f0565b9050919050565b6109658282610960612229565b612230565b5050565b5f60115f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f0000000000000000000000000000000000000000000000000000000000000000610a09610c9f565b10610a49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a4090614003565b60405180910390fd5b5f60145411610a8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a849061406b565b60405180910390fd5b60105f9054906101000a900460ff16610b44575f60039050610aae33610969565b15610ac357600281610ac091906140b6565b90505b8060125f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410610b42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3990614133565b60405180910390fd5b505b60135f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33306014546040518463ffffffff1660e01b8152600401610ba493929190614151565b6020604051808303815f875af1158015610bc0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be4919061419a565b610c23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1a9061420f565b60405180910390fd5b5f610c2c612242565b9050610c3833826122e3565b60125f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610c859061422d565b919050555050565b60105f9054906101000a900460ff1681565b5f600880549050905090565b3373ffffffffffffffffffffffffffffffffffffffff16610ccb836117ea565b73ffffffffffffffffffffffffffffffffffffffff1614610d21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d18906142be565b60405180910390fd5b60135f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33306015546040518463ffffffff1660e01b8152600401610d8193929190614151565b6020604051808303815f875af1158015610d9d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dc1919061419a565b610e00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610df79061420f565b60405180910390fd5b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d5b959f483836040518363ffffffff1660e01b8152600401610e5c92919061432e565b5f604051808303815f87803b158015610e73575f80fd5b505af1158015610e85573d5f803e3d5ffd5b505050505050565b5f8111610ecf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ec6906143a6565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081610ef9610c9f565b610f0391906140b6565b1115610f44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3b9061440e565b60405180910390fd5b60105f9054906101000a900460ff16611007575f60039050610f6533610969565b15610f7a57600281610f7791906140b6565b90505b808260125f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054610fc491906140b6565b1115611005576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ffc90614133565b60405180910390fd5b505b5f81601454611016919061442c565b905060135f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330846040518463ffffffff1660e01b815260040161107693929190614151565b6020604051808303815f875af1158015611092573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110b6919061419a565b6110f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ec9061420f565b60405180910390fd5b5f5b82811015611188575f611108612242565b905061111433826122e3565b60105f9054906101000a900460ff1661117a5760125f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154809291906111749061422d565b91905055505b5080806001019150506110f7565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036111fd575f6040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016111f4919061378e565b60405180910390fd5b5f611210838361120b612229565b612300565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611286578382826040517f64283d7b00000000000000000000000000000000000000000000000000000000815260040161127d9392919061446d565b60405180910390fd5b50505050565b5f611296836119ed565b82106112db5782826040517fa57d13dc0000000000000000000000000000000000000000000000000000000081526004016112d29291906144a2565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b60135f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b3373ffffffffffffffffffffffffffffffffffffffff16611399826117ea565b73ffffffffffffffffffffffffffffffffffffffff16146113ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e6906142be565b60405180910390fd5b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663368004ed826040518263ffffffff1660e01b815260040161144991906138bd565b5f604051808303815f87803b158015611460575f80fd5b505af1158015611472573d5f803e3d5ffd5b5050505050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611508576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114ff90613f3e565b60405180910390fd5b8060105f6101000a81548160ff02191690831515021790555050565b61153e83838360405180602001604052805f815250611d3c565b505050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146115d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115c990613f3e565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611640576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163790614513565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016116b7919061378e565b602060405180830381865afa1580156116d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116f69190614545565b6040518363ffffffff1660e01b8152600401611713929190614590565b6020604051808303815f875af115801561172f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611753919061419a565b5050565b5f611760610c9f565b82106117a5575f826040517fa57d13dc00000000000000000000000000000000000000000000000000000000815260040161179c9291906144a2565b60405180910390fd5b600882815481106117b9576117b86145b7565b5b905f5260205f2001549050919050565b6012602052805f5260405f205f915090505481565b600c5481565b60155481565b5f6117f48261216a565b9050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461188a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161188190613f3e565b60405180910390fd5b5f5b815181101561191157600160115f8484815181106118ad576118ac6145b7565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550808060010191505061188c565b5050565b60145481565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146119aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119a190613f3e565b60405180910390fd5b8060135f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611a5e575f6040517f89c62b64000000000000000000000000000000000000000000000000000000008152600401611a55919061378e565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b611aab61241a565b611ab45f6124a1565b565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3c90613f3e565b60405180910390fd5b81600e9081611b549190614778565b5080600f9081611b649190614778565b505050565b600381565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054611ba590613f89565b80601f0160208091040260200160405190810160405280929190818152602001828054611bd190613f89565b8015611c1c5780601f10611bf357610100808354040283529160200191611c1c565b820191905f5260205f20905b815481529060010190602001808311611bff57829003601f168201915b5050505050905090565b611c38611c31612229565b8383612564565b5050565b3373ffffffffffffffffffffffffffffffffffffffff16611c5c826117ea565b73ffffffffffffffffffffffffffffffffffffffff1614611cb2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ca9906142be565b60405180910390fd5b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b07f0a41826040518263ffffffff1660e01b8152600401611d0c91906138bd565b5f604051808303815f87803b158015611d23575f80fd5b505af1158015611d35573d5f803e3d5ffd5b5050505050565b611d4784848461118d565b611d5b611d52612229565b858585856126cd565b50505050565b60607f00000000000000000000000000000000000000000000000000000000000000008210611dc5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dbc90614891565b60405180910390fd5b5f600e611dd184612879565b604051602001611de29291906149b3565b60405160208183030381529060405290505f600f611dff85612879565b604051602001611e10929190614a2b565b60405160208183030381529060405290505f600e611e2d86612879565b604051602001611e3e929190614a2b565b60405160208183030381529060405290505f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e1dc0761876040518263ffffffff1660e01b8152600401611eaa91906138bd565b5f60405180830381865afa158015611ec4573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611eec9190614ac7565b9050611f28611efa87612879565b8584858786604051602001611f1496959493929190614daa565b6040516020818303038152906040526129d2565b604051602001611f389190614ea3565b604051602081830303815290604052945050505050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b61200d61241a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361207d575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401612074919061378e565b60405180910390fd5b612086816124a1565b50565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061215357507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806121635750612162826129ff565b5b9050919050565b5f8061217583612a68565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036121e757826040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016121de91906138bd565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b61223d8383836001612aa1565b505050565b5f80600c5411612287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161227e90614f0e565b60405180910390fd5b5f600c547f00000000000000000000000000000000000000000000000000000000000000006122b69190614f2c565b90505f6122c282612c60565b9050600c5f8154809291906122d690614f5f565b9190505550809250505090565b6122fc828260405180602001604052805f815250612ccd565b5050565b5f8061230d858585612cf0565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036123505761234b84612efb565b61238f565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461238e5761238d8185612f3f565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036123d0576123cb84613016565b61240f565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461240e5761240d85856130d6565b5b5b809150509392505050565b612422612229565b73ffffffffffffffffffffffffffffffffffffffff16612440611b6e565b73ffffffffffffffffffffffffffffffffffffffff161461249f57612463612229565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401612496919061378e565b60405180910390fd5b565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036125d457816040517f5b08ba180000000000000000000000000000000000000000000000000000000081526004016125cb919061378e565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516126c0919061360a565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115612872578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b815260040161272b9493929190614f86565b6020604051808303815f875af192505050801561276657506040513d601f19601f820116820180604052508101906127639190614fe4565b60015b6127e7573d805f8114612794576040519150601f19603f3d011682016040523d82523d5f602084013e612799565b606091505b505f8151036127df57836040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016127d6919061378e565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461287057836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612867919061378e565b60405180910390fd5b505b5050505050565b60605f82036128bf576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506129cd565b5f8290505f5b5f82146128ee5780806128d79061422d565b915050600a826128e7919061503c565b91506128c5565b5f8167ffffffffffffffff811115612909576129086138de565b5b6040519080825280601f01601f19166020018201604052801561293b5781602001600182028036833780820191505090505b5090505b5f85146129c6576001826129539190614f2c565b9150600a85612962919061506c565b603061296e91906140b6565b60f81b818381518110612984576129836145b7565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a856129bf919061503c565b945061293f565b8093505050505b919050565b60606129f8826040518060600160405280604081526020016150ca60409139600161315a565b9050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8080612ad957505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15612c0b575f612ae88461216a565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612b5257508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015612b655750612b638184611f77565b155b15612ba757826040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152600401612b9e919061378e565b60405180910390fd5b8115612c0957838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b5f806108ad90505f60018083612c769190614f2c565b7f0000000000000000000000000000000000000000000000000000000000000000612ca1919061506c565b612cab91906140b6565b9050818482612cba919061442c565b612cc4919061506c565b92505050919050565b612cd783836132e9565b612ceb612ce2612229565b5f8585856126cd565b505050565b5f80612cfb84612a68565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612d3c57612d3b8184866133dc565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612dc757612d7b5f855f80612aa1565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612e4657600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f612f49836119ed565b90505f60075f8481526020019081526020015f205490505f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050828214612fe8575f815f8581526020019081526020015f2054905080825f8581526020019081526020015f20819055508260075f8381526020019081526020015f2081905550505b60075f8581526020019081526020015f205f9055805f8481526020019081526020015f205f90555050505050565b5f60016008805490506130299190614f2c565b90505f60095f8481526020019081526020015f205490505f60088381548110613055576130546145b7565b5b905f5260205f20015490508060088381548110613075576130746145b7565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f905560088054806130bd576130bc61509c565b5b600190038181905f5260205f20015f9055905550505050565b5f60016130e2846119ed565b6130ec9190614f2c565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b60605f84510361317a5760405180602001604052805f81525090506132e2565b5f826131ab576003600286516004613192919061442c565b61319c91906140b6565b6131a6919061503c565b6131d2565b6003600286516131bb91906140b6565b6131c5919061503c565b60046131d1919061442c565b5b90505f8167ffffffffffffffff8111156131ef576131ee6138de565b5b6040519080825280601f01601f1916602001820160405280156132215781602001600182028036833780820191505090505b509050600185016020820187885189016020810180515f82525b82841015613296576003840193508351603f8160121c168701518653600186019550603f81600c1c168701518653600186019550603f8160061c168701518653600186019550603f811687015186536001860195505061323b565b80825289156132d65760038c5106600181146132b957600281146132cc576132d4565b603d6001870353603d60028703536132d4565b603d60018703535b505b50505050505080925050505b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613359575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401613350919061378e565b60405180910390fd5b5f61336583835f612300565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146133d7575f6040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081526004016133ce919061378e565b60405180910390fd5b505050565b6133e783838361349f565b61349a575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361345b57806040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161345291906138bd565b60405180910390fd5b81816040517f177e802f0000000000000000000000000000000000000000000000000000000081526004016134919291906144a2565b60405180910390fd5b505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561355657508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061351757506135168484611f77565b5b8061355557508273ffffffffffffffffffffffffffffffffffffffff1661353d836121f0565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6135a481613570565b81146135ae575f80fd5b50565b5f813590506135bf8161359b565b92915050565b5f602082840312156135da576135d9613568565b5b5f6135e7848285016135b1565b91505092915050565b5f8115159050919050565b613604816135f0565b82525050565b5f60208201905061361d5f8301846135fb565b92915050565b5f819050919050565b61363581613623565b811461363f575f80fd5b50565b5f813590506136508161362c565b92915050565b5f806040838503121561366c5761366b613568565b5b5f61367985828601613642565b925050602061368a85828601613642565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6136d682613694565b6136e0818561369e565b93506136f08185602086016136ae565b6136f9816136bc565b840191505092915050565b5f6020820190508181035f83015261371c81846136cc565b905092915050565b5f6020828403121561373957613738613568565b5b5f61374684828501613642565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6137788261374f565b9050919050565b6137888161376e565b82525050565b5f6020820190506137a15f83018461377f565b92915050565b6137b08161376e565b81146137ba575f80fd5b50565b5f813590506137cb816137a7565b92915050565b5f80604083850312156137e7576137e6613568565b5b5f6137f4858286016137bd565b925050602061380585828601613642565b9150509250929050565b5f6020828403121561382457613823613568565b5b5f613831848285016137bd565b91505092915050565b5f819050919050565b5f61385d6138586138538461374f565b61383a565b61374f565b9050919050565b5f61386e82613843565b9050919050565b5f61387f82613864565b9050919050565b61388f81613875565b82525050565b5f6020820190506138a85f830184613886565b92915050565b6138b781613623565b82525050565b5f6020820190506138d05f8301846138ae565b92915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613914826136bc565b810181811067ffffffffffffffff82111715613933576139326138de565b5b80604052505050565b5f61394561355f565b9050613951828261390b565b919050565b5f67ffffffffffffffff8211156139705761396f6138de565b5b613979826136bc565b9050602081019050919050565b828183375f83830152505050565b5f6139a66139a184613956565b61393c565b9050828152602081018484840111156139c2576139c16138da565b5b6139cd848285613986565b509392505050565b5f82601f8301126139e9576139e86138d6565b5b81356139f9848260208601613994565b91505092915050565b5f8060408385031215613a1857613a17613568565b5b5f613a2585828601613642565b925050602083013567ffffffffffffffff811115613a4657613a4561356c565b5b613a52858286016139d5565b9150509250929050565b5f805f60608486031215613a7357613a72613568565b5b5f613a80868287016137bd565b9350506020613a91868287016137bd565b9250506040613aa286828701613642565b9150509250925092565b5f613ab682613864565b9050919050565b613ac681613aac565b82525050565b5f602082019050613adf5f830184613abd565b92915050565b613aee816135f0565b8114613af8575f80fd5b50565b5f81359050613b0981613ae5565b92915050565b5f60208284031215613b2457613b23613568565b5b5f613b3184828501613afb565b91505092915050565b5f613b448261376e565b9050919050565b613b5481613b3a565b8114613b5e575f80fd5b50565b5f81359050613b6f81613b4b565b92915050565b5f60208284031215613b8a57613b89613568565b5b5f613b9784828501613b61565b91505092915050565b5f67ffffffffffffffff821115613bba57613bb96138de565b5b602082029050602081019050919050565b5f80fd5b5f613be1613bdc84613ba0565b61393c565b90508083825260208201905060208402830185811115613c0457613c03613bcb565b5b835b81811015613c2d5780613c1988826137bd565b845260208401935050602081019050613c06565b5050509392505050565b5f82601f830112613c4b57613c4a6138d6565b5b8135613c5b848260208601613bcf565b91505092915050565b5f60208284031215613c7957613c78613568565b5b5f82013567ffffffffffffffff811115613c9657613c9561356c565b5b613ca284828501613c37565b91505092915050565b5f67ffffffffffffffff821115613cc557613cc46138de565b5b613cce826136bc565b9050602081019050919050565b5f613ced613ce884613cab565b61393c565b905082815260208101848484011115613d0957613d086138da565b5b613d14848285613986565b509392505050565b5f82601f830112613d3057613d2f6138d6565b5b8135613d40848260208601613cdb565b91505092915050565b5f8060408385031215613d5f57613d5e613568565b5b5f83013567ffffffffffffffff811115613d7c57613d7b61356c565b5b613d8885828601613d1c565b925050602083013567ffffffffffffffff811115613da957613da861356c565b5b613db585828601613d1c565b9150509250929050565b5f8060408385031215613dd557613dd4613568565b5b5f613de2858286016137bd565b9250506020613df385828601613afb565b9150509250929050565b5f805f8060808587031215613e1557613e14613568565b5b5f613e22878288016137bd565b9450506020613e33878288016137bd565b9350506040613e4487828801613642565b925050606085013567ffffffffffffffff811115613e6557613e6461356c565b5b613e71878288016139d5565b91505092959194509250565b5f613e878261374f565b9050919050565b613e9781613e7d565b82525050565b5f602082019050613eb05f830184613e8e565b92915050565b5f8060408385031215613ecc57613ecb613568565b5b5f613ed9858286016137bd565b9250506020613eea858286016137bd565b9150509250929050565b7f4f6e6c79204465706c6f7965722e0000000000000000000000000000000000005f82015250565b5f613f28600e8361369e565b9150613f3382613ef4565b602082019050919050565b5f6020820190508181035f830152613f5581613f1c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613fa057607f821691505b602082108103613fb357613fb2613f5c565b5b50919050565b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f613fed60128361369e565b9150613ff882613fb9565b602082019050919050565b5f6020820190508181035f83015261401a81613fe1565b9050919050565b7f4d696e74696e67206e6f7420656e61626c6564000000000000000000000000005f82015250565b5f61405560138361369e565b915061406082614021565b602082019050919050565b5f6020820190508181035f83015261408281614049565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6140c082613623565b91506140cb83613623565b92508282019050808211156140e3576140e2614089565b5b92915050565b7f45786365656473206d696e74206c696d697400000000000000000000000000005f82015250565b5f61411d60128361369e565b9150614128826140e9565b602082019050919050565b5f6020820190508181035f83015261414a81614111565b9050919050565b5f6060820190506141645f83018661377f565b614171602083018561377f565b61417e60408301846138ae565b949350505050565b5f8151905061419481613ae5565b92915050565b5f602082840312156141af576141ae613568565b5b5f6141bc84828501614186565b91505092915050565b7f5061796d656e74206661696c65640000000000000000000000000000000000005f82015250565b5f6141f9600e8361369e565b9150614204826141c5565b602082019050919050565b5f6020820190508181035f830152614226816141ed565b9050919050565b5f61423782613623565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361426957614268614089565b5b600182019050919050565b7f4e6f7420746f6b656e206f776e657200000000000000000000000000000000005f82015250565b5f6142a8600f8361369e565b91506142b382614274565b602082019050919050565b5f6020820190508181035f8301526142d58161429c565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f614300826142dc565b61430a81856142e6565b935061431a8185602086016136ae565b614323816136bc565b840191505092915050565b5f6040820190506143415f8301856138ae565b818103602083015261435381846142f6565b90509392505050565b7f436f756e74206d757374206265203e20300000000000000000000000000000005f82015250565b5f61439060118361369e565b915061439b8261435c565b602082019050919050565b5f6020820190508181035f8301526143bd81614384565b9050919050565b7f45786365656473206d617820737570706c7900000000000000000000000000005f82015250565b5f6143f860128361369e565b9150614403826143c4565b602082019050919050565b5f6020820190508181035f830152614425816143ec565b9050919050565b5f61443682613623565b915061444183613623565b925082820261444f81613623565b9150828204841483151761446657614465614089565b5b5092915050565b5f6060820190506144805f83018661377f565b61448d60208301856138ae565b61449a604083018461377f565b949350505050565b5f6040820190506144b55f83018561377f565b6144c260208301846138ae565b9392505050565b7f496e76616c696420746f6b656e000000000000000000000000000000000000005f82015250565b5f6144fd600d8361369e565b9150614508826144c9565b602082019050919050565b5f6020820190508181035f83015261452a816144f1565b9050919050565b5f8151905061453f8161362c565b92915050565b5f6020828403121561455a57614559613568565b5b5f61456784828501614531565b91505092915050565b5f61457a82613864565b9050919050565b61458a81614570565b82525050565b5f6040820190506145a35f830185614581565b6145b060208301846138ae565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026146407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614605565b61464a8683614605565b95508019841693508086168417925050509392505050565b5f61467c61467761467284613623565b61383a565b613623565b9050919050565b5f819050919050565b61469583614662565b6146a96146a182614683565b848454614611565b825550505050565b5f90565b6146bd6146b1565b6146c881848461468c565b505050565b5b818110156146eb576146e05f826146b5565b6001810190506146ce565b5050565b601f82111561473057614701816145e4565b61470a846145f6565b81016020851015614719578190505b61472d614725856145f6565b8301826146cd565b50505b505050565b5f82821c905092915050565b5f6147505f1984600802614735565b1980831691505092915050565b5f6147688383614741565b9150826002028217905092915050565b61478182613694565b67ffffffffffffffff81111561479a576147996138de565b5b6147a48254613f89565b6147af8282856146ef565b5f60209050601f8311600181146147e0575f84156147ce578287015190505b6147d8858261475d565b86555061483f565b601f1984166147ee866145e4565b5f5b82811015614815578489015182556001820191506020850194506020810190506147f0565b86831015614832578489015161482e601f891682614741565b8355505b6001600288020188555050505b505050505050565b7f546f6b656e20646f6573206e6f742065786973740000000000000000000000005f82015250565b5f61487b60148361369e565b915061488682614847565b602082019050919050565b5f6020820190508181035f8301526148a88161486f565b9050919050565b5f81905092915050565b5f81546148c581613f89565b6148cf81866148af565b9450600182165f81146148e957600181146148fe57614930565b60ff1983168652811515820286019350614930565b614907856145e4565b5f5b8381101561492857815481890152600182019150602081019050614909565b838801955050505b50505092915050565b7f2f6170692f696d6167652f0000000000000000000000000000000000000000005f82015250565b5f61496d600b836148af565b915061497882614939565b600b82019050919050565b5f61498d82613694565b61499781856148af565b93506149a78185602086016136ae565b80840191505092915050565b5f6149be82856148b9565b91506149c982614961565b91506149d58284614983565b91508190509392505050565b7f2f746f6b656e2f000000000000000000000000000000000000000000000000005f82015250565b5f614a156007836148af565b9150614a20826149e1565b600782019050919050565b5f614a3682856148b9565b9150614a4182614a09565b9150614a4d8284614983565b91508190509392505050565b5f614a6b614a6684613cab565b61393c565b905082815260208101848484011115614a8757614a866138da565b5b614a928482856136ae565b509392505050565b5f82601f830112614aae57614aad6138d6565b5b8151614abe848260208601614a59565b91505092915050565b5f60208284031215614adc57614adb613568565b5b5f82015167ffffffffffffffff811115614af957614af861356c565b5b614b0584828501614a9a565b91505092915050565b7f7b226e616d65223a2250392023000000000000000000000000000000000000005f82015250565b5f614b42600d836148af565b9150614b4d82614b0e565b600d82019050919050565b7f222c20226465736372697074696f6e223a2250726f6a6563742039202d2073615f8201527f76696e6720656e64616e67657265642063726561747572657320696e20756e6360208201527f686172746564207265616c6d732e222c00000000000000000000000000000000604082015250565b5f614bd86050836148af565b9150614be382614b58565b605082019050919050565b7f22696d616765223a2200000000000000000000000000000000000000000000005f82015250565b5f614c226009836148af565b9150614c2d82614bee565b600982019050919050565b7f222c2022616e696d6174696f6e5f75726c223a220000000000000000000000005f82015250565b5f614c6c6014836148af565b9150614c7782614c38565b601482019050919050565b7f222c2022696672616d655f75726c223a220000000000000000000000000000005f82015250565b5f614cb66011836148af565b9150614cc182614c82565b601182019050919050565b7f222c202265787465726e616c5f75726c223a22000000000000000000000000005f82015250565b5f614d006013836148af565b9150614d0b82614ccc565b601382019050919050565b7f222c202261747472696275746573223a000000000000000000000000000000005f82015250565b5f614d4a6010836148af565b9150614d5582614d16565b601082019050919050565b7f7d000000000000000000000000000000000000000000000000000000000000005f82015250565b5f614d946001836148af565b9150614d9f82614d60565b600182019050919050565b5f614db482614b36565b9150614dc08289614983565b9150614dcb82614bcc565b9150614dd682614c16565b9150614de28288614983565b9150614ded82614c60565b9150614df98287614983565b9150614e0482614caa565b9150614e108286614983565b9150614e1b82614cf4565b9150614e278285614983565b9150614e3282614d3e565b9150614e3e8284614983565b9150614e4982614d88565b9150819050979650505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f614e8d601d836148af565b9150614e9882614e59565b601d82019050919050565b5f614ead82614e81565b9150614eb98284614983565b915081905092915050565b7f416c6c206d696e746564000000000000000000000000000000000000000000005f82015250565b5f614ef8600a8361369e565b9150614f0382614ec4565b602082019050919050565b5f6020820190508181035f830152614f2581614eec565b9050919050565b5f614f3682613623565b9150614f4183613623565b9250828203905081811115614f5957614f58614089565b5b92915050565b5f614f6982613623565b91505f8203614f7b57614f7a614089565b5b600182039050919050565b5f608082019050614f995f83018761377f565b614fa6602083018661377f565b614fb360408301856138ae565b8181036060830152614fc581846142f6565b905095945050505050565b5f81519050614fde8161359b565b92915050565b5f60208284031215614ff957614ff8613568565b5b5f61500684828501614fd0565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61504682613623565b915061505183613623565b9250826150615761506061500f565b5b828204905092915050565b5f61507682613623565b915061508183613623565b9250826150915761509061500f565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220da5b6f6052b5d02e9631e638043fa34b7ca3c422daf53eda1cce189bb7607ab564736f6c634300081a00330000000000000000000000005c8cd93cffa0181ca63331c0c6b43f5d30149c94000000000000000000000000b931e339b4f5eb3d4d039ce1451426754063c711
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610251575f3560e01c80634f6ccce71161014457806380796bbf116100c1578063b07f0a4111610085578063b07f0a41146106bd578063b88d4fde146106d9578063c87b56dd146106f5578063d5f3948814610725578063e985e9c514610743578063f2fde38b1461077357610251565b806380796bbf1461062b5780638099b002146106475780638da5cb5b1461066557806395d89b4114610683578063a22cb465146106a157610251565b806367b06aee1161010857806367b06aee1461059b5780636817c76c146105b75780636a326ab1146105d557806370a08231146105f1578063715018a61461062157610251565b80634f6ccce7146104cf57806353277879146104ff57806355234ec01461052f578063584430e61461054d5780636352211e1461056b57610251565b80632061cea7116101d257806332cb6b0c1161019657806332cb6b0c14610441578063368004ed1461045f5780633a87d2851461047b57806342842e0e1461049757806349df728c146104b357610251565b80632061cea71461039f57806320e409b4146103bb57806323b872dd146103d75780632f745c59146103f35780633013ce291461042357610251565b806309fd82121161021957806309fd82121461030b5780630d6688181461033b5780631249c58b1461035957806315f04ccd1461036357806318160ddd1461038157610251565b806301ffc9a71461025557806305fefda71461028557806306fdde03146102a1578063081812fc146102bf578063095ea7b3146102ef575b5f80fd5b61026f600480360381019061026a91906135c5565b61078f565b60405161027c919061360a565b60405180910390f35b61029f600480360381019061029a9190613656565b610808565b005b6102a96108a9565b6040516102b69190613704565b60405180910390f35b6102d960048036038101906102d49190613724565b610938565b6040516102e6919061378e565b60405180910390f35b610309600480360381019061030491906137d1565b610953565b005b6103256004803603810190610320919061380f565b610969565b604051610332919061360a565b60405180910390f35b6103436109bb565b6040516103509190613895565b60405180910390f35b6103616109e0565b005b61036b610c8d565b604051610378919061360a565b60405180910390f35b610389610c9f565b60405161039691906138bd565b60405180910390f35b6103b960048036038101906103b49190613a02565b610cab565b005b6103d560048036038101906103d09190613724565b610e8d565b005b6103f160048036038101906103ec9190613a5c565b61118d565b005b61040d600480360381019061040891906137d1565b61128c565b60405161041a91906138bd565b60405180910390f35b61042b611330565b6040516104389190613acc565b60405180910390f35b610449611355565b60405161045691906138bd565b60405180910390f35b61047960048036038101906104749190613724565b611379565b005b61049560048036038101906104909190613b0f565b611479565b005b6104b160048036038101906104ac9190613a5c565b611524565b005b6104cd60048036038101906104c89190613b75565b611543565b005b6104e960048036038101906104e49190613724565b611757565b6040516104f691906138bd565b60405180910390f35b6105196004803603810190610514919061380f565b6117c9565b60405161052691906138bd565b60405180910390f35b6105376117de565b60405161054491906138bd565b60405180910390f35b6105556117e4565b60405161056291906138bd565b60405180910390f35b61058560048036038101906105809190613724565b6117ea565b604051610592919061378e565b60405180910390f35b6105b560048036038101906105b09190613c64565b6117fb565b005b6105bf611915565b6040516105cc91906138bd565b60405180910390f35b6105ef60048036038101906105ea919061380f565b61191b565b005b61060b6004803603810190610606919061380f565b6119ed565b60405161061891906138bd565b60405180910390f35b610629611aa3565b005b61064560048036038101906106409190613d49565b611ab6565b005b61064f611b69565b60405161065c91906138bd565b60405180910390f35b61066d611b6e565b60405161067a919061378e565b60405180910390f35b61068b611b96565b6040516106989190613704565b60405180910390f35b6106bb60048036038101906106b69190613dbf565b611c26565b005b6106d760048036038101906106d29190613724565b611c3c565b005b6106f360048036038101906106ee9190613dfd565b611d3c565b005b61070f600480360381019061070a9190613724565b611d61565b60405161071c9190613704565b60405180910390f35b61072d611f52565b60405161073a9190613e9d565b60405180910390f35b61075d60048036038101906107589190613eb6565b611f77565b60405161076a919061360a565b60405180910390f35b61078d6004803603810190610788919061380f565b612005565b005b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610801575061080082612089565b5b9050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088e90613f3e565b60405180910390fd5b81601481905550806015819055505050565b60605f80546108b790613f89565b80601f01602080910402602001604051908101604052809291908181526020018280546108e390613f89565b801561092e5780601f106109055761010080835404028352916020019161092e565b820191905f5260205f20905b81548152906001019060200180831161091157829003601f168201915b5050505050905090565b5f6109428261216a565b5061094c826121f0565b9050919050565b6109658282610960612229565b612230565b5050565b5f60115f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000008ae610a09610c9f565b10610a49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a4090614003565b60405180910390fd5b5f60145411610a8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a849061406b565b60405180910390fd5b60105f9054906101000a900460ff16610b44575f60039050610aae33610969565b15610ac357600281610ac091906140b6565b90505b8060125f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410610b42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3990614133565b60405180910390fd5b505b60135f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33306014546040518463ffffffff1660e01b8152600401610ba493929190614151565b6020604051808303815f875af1158015610bc0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be4919061419a565b610c23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1a9061420f565b60405180910390fd5b5f610c2c612242565b9050610c3833826122e3565b60125f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190610c859061422d565b919050555050565b60105f9054906101000a900460ff1681565b5f600880549050905090565b3373ffffffffffffffffffffffffffffffffffffffff16610ccb836117ea565b73ffffffffffffffffffffffffffffffffffffffff1614610d21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d18906142be565b60405180910390fd5b60135f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33306015546040518463ffffffff1660e01b8152600401610d8193929190614151565b6020604051808303815f875af1158015610d9d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dc1919061419a565b610e00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610df79061420f565b60405180910390fd5b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d5b959f483836040518363ffffffff1660e01b8152600401610e5c92919061432e565b5f604051808303815f87803b158015610e73575f80fd5b505af1158015610e85573d5f803e3d5ffd5b505050505050565b5f8111610ecf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ec6906143a6565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000008ae81610ef9610c9f565b610f0391906140b6565b1115610f44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3b9061440e565b60405180910390fd5b60105f9054906101000a900460ff16611007575f60039050610f6533610969565b15610f7a57600281610f7791906140b6565b90505b808260125f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054610fc491906140b6565b1115611005576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ffc90614133565b60405180910390fd5b505b5f81601454611016919061442c565b905060135f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330846040518463ffffffff1660e01b815260040161107693929190614151565b6020604051808303815f875af1158015611092573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110b6919061419a565b6110f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ec9061420f565b60405180910390fd5b5f5b82811015611188575f611108612242565b905061111433826122e3565b60105f9054906101000a900460ff1661117a5760125f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154809291906111749061422d565b91905055505b5080806001019150506110f7565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036111fd575f6040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016111f4919061378e565b60405180910390fd5b5f611210838361120b612229565b612300565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611286578382826040517f64283d7b00000000000000000000000000000000000000000000000000000000815260040161127d9392919061446d565b60405180910390fd5b50505050565b5f611296836119ed565b82106112db5782826040517fa57d13dc0000000000000000000000000000000000000000000000000000000081526004016112d29291906144a2565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b60135f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000008ae81565b3373ffffffffffffffffffffffffffffffffffffffff16611399826117ea565b73ffffffffffffffffffffffffffffffffffffffff16146113ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e6906142be565b60405180910390fd5b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663368004ed826040518263ffffffff1660e01b815260040161144991906138bd565b5f604051808303815f87803b158015611460575f80fd5b505af1158015611472573d5f803e3d5ffd5b5050505050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611508576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114ff90613f3e565b60405180910390fd5b8060105f6101000a81548160ff02191690831515021790555050565b61153e83838360405180602001604052805f815250611d3c565b505050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146115d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115c990613f3e565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611640576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163790614513565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016116b7919061378e565b602060405180830381865afa1580156116d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116f69190614545565b6040518363ffffffff1660e01b8152600401611713929190614590565b6020604051808303815f875af115801561172f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611753919061419a565b5050565b5f611760610c9f565b82106117a5575f826040517fa57d13dc00000000000000000000000000000000000000000000000000000000815260040161179c9291906144a2565b60405180910390fd5b600882815481106117b9576117b86145b7565b5b905f5260205f2001549050919050565b6012602052805f5260405f205f915090505481565b600c5481565b60155481565b5f6117f48261216a565b9050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461188a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161188190613f3e565b60405180910390fd5b5f5b815181101561191157600160115f8484815181106118ad576118ac6145b7565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550808060010191505061188c565b5050565b60145481565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146119aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119a190613f3e565b60405180910390fd5b8060135f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611a5e575f6040517f89c62b64000000000000000000000000000000000000000000000000000000008152600401611a55919061378e565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b611aab61241a565b611ab45f6124a1565b565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3c90613f3e565b60405180910390fd5b81600e9081611b549190614778565b5080600f9081611b649190614778565b505050565b600381565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054611ba590613f89565b80601f0160208091040260200160405190810160405280929190818152602001828054611bd190613f89565b8015611c1c5780601f10611bf357610100808354040283529160200191611c1c565b820191905f5260205f20905b815481529060010190602001808311611bff57829003601f168201915b5050505050905090565b611c38611c31612229565b8383612564565b5050565b3373ffffffffffffffffffffffffffffffffffffffff16611c5c826117ea565b73ffffffffffffffffffffffffffffffffffffffff1614611cb2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ca9906142be565b60405180910390fd5b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b07f0a41826040518263ffffffff1660e01b8152600401611d0c91906138bd565b5f604051808303815f87803b158015611d23575f80fd5b505af1158015611d35573d5f803e3d5ffd5b5050505050565b611d4784848461118d565b611d5b611d52612229565b858585856126cd565b50505050565b60607f00000000000000000000000000000000000000000000000000000000000008ae8210611dc5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dbc90614891565b60405180910390fd5b5f600e611dd184612879565b604051602001611de29291906149b3565b60405160208183030381529060405290505f600f611dff85612879565b604051602001611e10929190614a2b565b60405160208183030381529060405290505f600e611e2d86612879565b604051602001611e3e929190614a2b565b60405160208183030381529060405290505f600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e1dc0761876040518263ffffffff1660e01b8152600401611eaa91906138bd565b5f60405180830381865afa158015611ec4573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611eec9190614ac7565b9050611f28611efa87612879565b8584858786604051602001611f1496959493929190614daa565b6040516020818303038152906040526129d2565b604051602001611f389190614ea3565b604051602081830303815290604052945050505050919050565b600d5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b61200d61241a565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361207d575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401612074919061378e565b60405180910390fd5b612086816124a1565b50565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061215357507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806121635750612162826129ff565b5b9050919050565b5f8061217583612a68565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036121e757826040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016121de91906138bd565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b61223d8383836001612aa1565b505050565b5f80600c5411612287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161227e90614f0e565b60405180910390fd5b5f600c547f00000000000000000000000000000000000000000000000000000000000008ae6122b69190614f2c565b90505f6122c282612c60565b9050600c5f8154809291906122d690614f5f565b9190505550809250505090565b6122fc828260405180602001604052805f815250612ccd565b5050565b5f8061230d858585612cf0565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036123505761234b84612efb565b61238f565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461238e5761238d8185612f3f565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036123d0576123cb84613016565b61240f565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461240e5761240d85856130d6565b5b5b809150509392505050565b612422612229565b73ffffffffffffffffffffffffffffffffffffffff16612440611b6e565b73ffffffffffffffffffffffffffffffffffffffff161461249f57612463612229565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401612496919061378e565b60405180910390fd5b565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036125d457816040517f5b08ba180000000000000000000000000000000000000000000000000000000081526004016125cb919061378e565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516126c0919061360a565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115612872578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b815260040161272b9493929190614f86565b6020604051808303815f875af192505050801561276657506040513d601f19601f820116820180604052508101906127639190614fe4565b60015b6127e7573d805f8114612794576040519150601f19603f3d011682016040523d82523d5f602084013e612799565b606091505b505f8151036127df57836040517f64a0ae920000000000000000000000000000000000000000000000000000000081526004016127d6919061378e565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461287057836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612867919061378e565b60405180910390fd5b505b5050505050565b60605f82036128bf576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506129cd565b5f8290505f5b5f82146128ee5780806128d79061422d565b915050600a826128e7919061503c565b91506128c5565b5f8167ffffffffffffffff811115612909576129086138de565b5b6040519080825280601f01601f19166020018201604052801561293b5781602001600182028036833780820191505090505b5090505b5f85146129c6576001826129539190614f2c565b9150600a85612962919061506c565b603061296e91906140b6565b60f81b818381518110612984576129836145b7565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a856129bf919061503c565b945061293f565b8093505050505b919050565b60606129f8826040518060600160405280604081526020016150ca60409139600161315a565b9050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8080612ad957505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15612c0b575f612ae88461216a565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612b5257508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015612b655750612b638184611f77565b155b15612ba757826040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152600401612b9e919061378e565b60405180910390fd5b8115612c0957838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b5f806108ad90505f60018083612c769190614f2c565b7fb960bbe2084ea42a957491a5285ac5a16700365a4d9c185d1e5906bdc5ae183d612ca1919061506c565b612cab91906140b6565b9050818482612cba919061442c565b612cc4919061506c565b92505050919050565b612cd783836132e9565b612ceb612ce2612229565b5f8585856126cd565b505050565b5f80612cfb84612a68565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612d3c57612d3b8184866133dc565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612dc757612d7b5f855f80612aa1565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612e4657600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f612f49836119ed565b90505f60075f8481526020019081526020015f205490505f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050828214612fe8575f815f8581526020019081526020015f2054905080825f8581526020019081526020015f20819055508260075f8381526020019081526020015f2081905550505b60075f8581526020019081526020015f205f9055805f8481526020019081526020015f205f90555050505050565b5f60016008805490506130299190614f2c565b90505f60095f8481526020019081526020015f205490505f60088381548110613055576130546145b7565b5b905f5260205f20015490508060088381548110613075576130746145b7565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f905560088054806130bd576130bc61509c565b5b600190038181905f5260205f20015f9055905550505050565b5f60016130e2846119ed565b6130ec9190614f2c565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b60605f84510361317a5760405180602001604052805f81525090506132e2565b5f826131ab576003600286516004613192919061442c565b61319c91906140b6565b6131a6919061503c565b6131d2565b6003600286516131bb91906140b6565b6131c5919061503c565b60046131d1919061442c565b5b90505f8167ffffffffffffffff8111156131ef576131ee6138de565b5b6040519080825280601f01601f1916602001820160405280156132215781602001600182028036833780820191505090505b509050600185016020820187885189016020810180515f82525b82841015613296576003840193508351603f8160121c168701518653600186019550603f81600c1c168701518653600186019550603f8160061c168701518653600186019550603f811687015186536001860195505061323b565b80825289156132d65760038c5106600181146132b957600281146132cc576132d4565b603d6001870353603d60028703536132d4565b603d60018703535b505b50505050505080925050505b9392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613359575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401613350919061378e565b60405180910390fd5b5f61336583835f612300565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146133d7575f6040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081526004016133ce919061378e565b60405180910390fd5b505050565b6133e783838361349f565b61349a575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361345b57806040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161345291906138bd565b60405180910390fd5b81816040517f177e802f0000000000000000000000000000000000000000000000000000000081526004016134919291906144a2565b60405180910390fd5b505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561355657508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061351757506135168484611f77565b5b8061355557508273ffffffffffffffffffffffffffffffffffffffff1661353d836121f0565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6135a481613570565b81146135ae575f80fd5b50565b5f813590506135bf8161359b565b92915050565b5f602082840312156135da576135d9613568565b5b5f6135e7848285016135b1565b91505092915050565b5f8115159050919050565b613604816135f0565b82525050565b5f60208201905061361d5f8301846135fb565b92915050565b5f819050919050565b61363581613623565b811461363f575f80fd5b50565b5f813590506136508161362c565b92915050565b5f806040838503121561366c5761366b613568565b5b5f61367985828601613642565b925050602061368a85828601613642565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6136d682613694565b6136e0818561369e565b93506136f08185602086016136ae565b6136f9816136bc565b840191505092915050565b5f6020820190508181035f83015261371c81846136cc565b905092915050565b5f6020828403121561373957613738613568565b5b5f61374684828501613642565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6137788261374f565b9050919050565b6137888161376e565b82525050565b5f6020820190506137a15f83018461377f565b92915050565b6137b08161376e565b81146137ba575f80fd5b50565b5f813590506137cb816137a7565b92915050565b5f80604083850312156137e7576137e6613568565b5b5f6137f4858286016137bd565b925050602061380585828601613642565b9150509250929050565b5f6020828403121561382457613823613568565b5b5f613831848285016137bd565b91505092915050565b5f819050919050565b5f61385d6138586138538461374f565b61383a565b61374f565b9050919050565b5f61386e82613843565b9050919050565b5f61387f82613864565b9050919050565b61388f81613875565b82525050565b5f6020820190506138a85f830184613886565b92915050565b6138b781613623565b82525050565b5f6020820190506138d05f8301846138ae565b92915050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613914826136bc565b810181811067ffffffffffffffff82111715613933576139326138de565b5b80604052505050565b5f61394561355f565b9050613951828261390b565b919050565b5f67ffffffffffffffff8211156139705761396f6138de565b5b613979826136bc565b9050602081019050919050565b828183375f83830152505050565b5f6139a66139a184613956565b61393c565b9050828152602081018484840111156139c2576139c16138da565b5b6139cd848285613986565b509392505050565b5f82601f8301126139e9576139e86138d6565b5b81356139f9848260208601613994565b91505092915050565b5f8060408385031215613a1857613a17613568565b5b5f613a2585828601613642565b925050602083013567ffffffffffffffff811115613a4657613a4561356c565b5b613a52858286016139d5565b9150509250929050565b5f805f60608486031215613a7357613a72613568565b5b5f613a80868287016137bd565b9350506020613a91868287016137bd565b9250506040613aa286828701613642565b9150509250925092565b5f613ab682613864565b9050919050565b613ac681613aac565b82525050565b5f602082019050613adf5f830184613abd565b92915050565b613aee816135f0565b8114613af8575f80fd5b50565b5f81359050613b0981613ae5565b92915050565b5f60208284031215613b2457613b23613568565b5b5f613b3184828501613afb565b91505092915050565b5f613b448261376e565b9050919050565b613b5481613b3a565b8114613b5e575f80fd5b50565b5f81359050613b6f81613b4b565b92915050565b5f60208284031215613b8a57613b89613568565b5b5f613b9784828501613b61565b91505092915050565b5f67ffffffffffffffff821115613bba57613bb96138de565b5b602082029050602081019050919050565b5f80fd5b5f613be1613bdc84613ba0565b61393c565b90508083825260208201905060208402830185811115613c0457613c03613bcb565b5b835b81811015613c2d5780613c1988826137bd565b845260208401935050602081019050613c06565b5050509392505050565b5f82601f830112613c4b57613c4a6138d6565b5b8135613c5b848260208601613bcf565b91505092915050565b5f60208284031215613c7957613c78613568565b5b5f82013567ffffffffffffffff811115613c9657613c9561356c565b5b613ca284828501613c37565b91505092915050565b5f67ffffffffffffffff821115613cc557613cc46138de565b5b613cce826136bc565b9050602081019050919050565b5f613ced613ce884613cab565b61393c565b905082815260208101848484011115613d0957613d086138da565b5b613d14848285613986565b509392505050565b5f82601f830112613d3057613d2f6138d6565b5b8135613d40848260208601613cdb565b91505092915050565b5f8060408385031215613d5f57613d5e613568565b5b5f83013567ffffffffffffffff811115613d7c57613d7b61356c565b5b613d8885828601613d1c565b925050602083013567ffffffffffffffff811115613da957613da861356c565b5b613db585828601613d1c565b9150509250929050565b5f8060408385031215613dd557613dd4613568565b5b5f613de2858286016137bd565b9250506020613df385828601613afb565b9150509250929050565b5f805f8060808587031215613e1557613e14613568565b5b5f613e22878288016137bd565b9450506020613e33878288016137bd565b9350506040613e4487828801613642565b925050606085013567ffffffffffffffff811115613e6557613e6461356c565b5b613e71878288016139d5565b91505092959194509250565b5f613e878261374f565b9050919050565b613e9781613e7d565b82525050565b5f602082019050613eb05f830184613e8e565b92915050565b5f8060408385031215613ecc57613ecb613568565b5b5f613ed9858286016137bd565b9250506020613eea858286016137bd565b9150509250929050565b7f4f6e6c79204465706c6f7965722e0000000000000000000000000000000000005f82015250565b5f613f28600e8361369e565b9150613f3382613ef4565b602082019050919050565b5f6020820190508181035f830152613f5581613f1c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613fa057607f821691505b602082108103613fb357613fb2613f5c565b5b50919050565b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f613fed60128361369e565b9150613ff882613fb9565b602082019050919050565b5f6020820190508181035f83015261401a81613fe1565b9050919050565b7f4d696e74696e67206e6f7420656e61626c6564000000000000000000000000005f82015250565b5f61405560138361369e565b915061406082614021565b602082019050919050565b5f6020820190508181035f83015261408281614049565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6140c082613623565b91506140cb83613623565b92508282019050808211156140e3576140e2614089565b5b92915050565b7f45786365656473206d696e74206c696d697400000000000000000000000000005f82015250565b5f61411d60128361369e565b9150614128826140e9565b602082019050919050565b5f6020820190508181035f83015261414a81614111565b9050919050565b5f6060820190506141645f83018661377f565b614171602083018561377f565b61417e60408301846138ae565b949350505050565b5f8151905061419481613ae5565b92915050565b5f602082840312156141af576141ae613568565b5b5f6141bc84828501614186565b91505092915050565b7f5061796d656e74206661696c65640000000000000000000000000000000000005f82015250565b5f6141f9600e8361369e565b9150614204826141c5565b602082019050919050565b5f6020820190508181035f830152614226816141ed565b9050919050565b5f61423782613623565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361426957614268614089565b5b600182019050919050565b7f4e6f7420746f6b656e206f776e657200000000000000000000000000000000005f82015250565b5f6142a8600f8361369e565b91506142b382614274565b602082019050919050565b5f6020820190508181035f8301526142d58161429c565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f614300826142dc565b61430a81856142e6565b935061431a8185602086016136ae565b614323816136bc565b840191505092915050565b5f6040820190506143415f8301856138ae565b818103602083015261435381846142f6565b90509392505050565b7f436f756e74206d757374206265203e20300000000000000000000000000000005f82015250565b5f61439060118361369e565b915061439b8261435c565b602082019050919050565b5f6020820190508181035f8301526143bd81614384565b9050919050565b7f45786365656473206d617820737570706c7900000000000000000000000000005f82015250565b5f6143f860128361369e565b9150614403826143c4565b602082019050919050565b5f6020820190508181035f830152614425816143ec565b9050919050565b5f61443682613623565b915061444183613623565b925082820261444f81613623565b9150828204841483151761446657614465614089565b5b5092915050565b5f6060820190506144805f83018661377f565b61448d60208301856138ae565b61449a604083018461377f565b949350505050565b5f6040820190506144b55f83018561377f565b6144c260208301846138ae565b9392505050565b7f496e76616c696420746f6b656e000000000000000000000000000000000000005f82015250565b5f6144fd600d8361369e565b9150614508826144c9565b602082019050919050565b5f6020820190508181035f83015261452a816144f1565b9050919050565b5f8151905061453f8161362c565b92915050565b5f6020828403121561455a57614559613568565b5b5f61456784828501614531565b91505092915050565b5f61457a82613864565b9050919050565b61458a81614570565b82525050565b5f6040820190506145a35f830185614581565b6145b060208301846138ae565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026146407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614605565b61464a8683614605565b95508019841693508086168417925050509392505050565b5f61467c61467761467284613623565b61383a565b613623565b9050919050565b5f819050919050565b61469583614662565b6146a96146a182614683565b848454614611565b825550505050565b5f90565b6146bd6146b1565b6146c881848461468c565b505050565b5b818110156146eb576146e05f826146b5565b6001810190506146ce565b5050565b601f82111561473057614701816145e4565b61470a846145f6565b81016020851015614719578190505b61472d614725856145f6565b8301826146cd565b50505b505050565b5f82821c905092915050565b5f6147505f1984600802614735565b1980831691505092915050565b5f6147688383614741565b9150826002028217905092915050565b61478182613694565b67ffffffffffffffff81111561479a576147996138de565b5b6147a48254613f89565b6147af8282856146ef565b5f60209050601f8311600181146147e0575f84156147ce578287015190505b6147d8858261475d565b86555061483f565b601f1984166147ee866145e4565b5f5b82811015614815578489015182556001820191506020850194506020810190506147f0565b86831015614832578489015161482e601f891682614741565b8355505b6001600288020188555050505b505050505050565b7f546f6b656e20646f6573206e6f742065786973740000000000000000000000005f82015250565b5f61487b60148361369e565b915061488682614847565b602082019050919050565b5f6020820190508181035f8301526148a88161486f565b9050919050565b5f81905092915050565b5f81546148c581613f89565b6148cf81866148af565b9450600182165f81146148e957600181146148fe57614930565b60ff1983168652811515820286019350614930565b614907856145e4565b5f5b8381101561492857815481890152600182019150602081019050614909565b838801955050505b50505092915050565b7f2f6170692f696d6167652f0000000000000000000000000000000000000000005f82015250565b5f61496d600b836148af565b915061497882614939565b600b82019050919050565b5f61498d82613694565b61499781856148af565b93506149a78185602086016136ae565b80840191505092915050565b5f6149be82856148b9565b91506149c982614961565b91506149d58284614983565b91508190509392505050565b7f2f746f6b656e2f000000000000000000000000000000000000000000000000005f82015250565b5f614a156007836148af565b9150614a20826149e1565b600782019050919050565b5f614a3682856148b9565b9150614a4182614a09565b9150614a4d8284614983565b91508190509392505050565b5f614a6b614a6684613cab565b61393c565b905082815260208101848484011115614a8757614a866138da565b5b614a928482856136ae565b509392505050565b5f82601f830112614aae57614aad6138d6565b5b8151614abe848260208601614a59565b91505092915050565b5f60208284031215614adc57614adb613568565b5b5f82015167ffffffffffffffff811115614af957614af861356c565b5b614b0584828501614a9a565b91505092915050565b7f7b226e616d65223a2250392023000000000000000000000000000000000000005f82015250565b5f614b42600d836148af565b9150614b4d82614b0e565b600d82019050919050565b7f222c20226465736372697074696f6e223a2250726f6a6563742039202d2073615f8201527f76696e6720656e64616e67657265642063726561747572657320696e20756e6360208201527f686172746564207265616c6d732e222c00000000000000000000000000000000604082015250565b5f614bd86050836148af565b9150614be382614b58565b605082019050919050565b7f22696d616765223a2200000000000000000000000000000000000000000000005f82015250565b5f614c226009836148af565b9150614c2d82614bee565b600982019050919050565b7f222c2022616e696d6174696f6e5f75726c223a220000000000000000000000005f82015250565b5f614c6c6014836148af565b9150614c7782614c38565b601482019050919050565b7f222c2022696672616d655f75726c223a220000000000000000000000000000005f82015250565b5f614cb66011836148af565b9150614cc182614c82565b601182019050919050565b7f222c202265787465726e616c5f75726c223a22000000000000000000000000005f82015250565b5f614d006013836148af565b9150614d0b82614ccc565b601382019050919050565b7f222c202261747472696275746573223a000000000000000000000000000000005f82015250565b5f614d4a6010836148af565b9150614d5582614d16565b601082019050919050565b7f7d000000000000000000000000000000000000000000000000000000000000005f82015250565b5f614d946001836148af565b9150614d9f82614d60565b600182019050919050565b5f614db482614b36565b9150614dc08289614983565b9150614dcb82614bcc565b9150614dd682614c16565b9150614de28288614983565b9150614ded82614c60565b9150614df98287614983565b9150614e0482614caa565b9150614e108286614983565b9150614e1b82614cf4565b9150614e278285614983565b9150614e3282614d3e565b9150614e3e8284614983565b9150614e4982614d88565b9150819050979650505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f614e8d601d836148af565b9150614e9882614e59565b601d82019050919050565b5f614ead82614e81565b9150614eb98284614983565b915081905092915050565b7f416c6c206d696e746564000000000000000000000000000000000000000000005f82015250565b5f614ef8600a8361369e565b9150614f0382614ec4565b602082019050919050565b5f6020820190508181035f830152614f2581614eec565b9050919050565b5f614f3682613623565b9150614f4183613623565b9250828203905081811115614f5957614f58614089565b5b92915050565b5f614f6982613623565b91505f8203614f7b57614f7a614089565b5b600182039050919050565b5f608082019050614f995f83018761377f565b614fa6602083018661377f565b614fb360408301856138ae565b8181036060830152614fc581846142f6565b905095945050505050565b5f81519050614fde8161359b565b92915050565b5f60208284031215614ff957614ff8613568565b5b5f61500684828501614fd0565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61504682613623565b915061505183613623565b9250826150615761506061500f565b5b828204905092915050565b5f61507682613623565b915061508183613623565b9250826150915761509061500f565b5b828206905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220da5b6f6052b5d02e9631e638043fa34b7ca3c422daf53eda1cce189bb7607ab564736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005c8cd93cffa0181ca63331c0c6b43f5d30149c94000000000000000000000000b931e339b4f5eb3d4d039ce1451426754063c711
-----Decoded View---------------
Arg [0] : dataContractAddress (address): 0x5C8cd93CFfA0181Ca63331c0c6b43f5D30149C94
Arg [1] : _deployer (address): 0xb931E339b4f5eB3D4D039CE1451426754063C711
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000005c8cd93cffa0181ca63331c0c6b43f5d30149c94
Arg [1] : 000000000000000000000000b931e339b4f5eb3d4d039ce1451426754063c711
Deployed Bytecode Sourcemap
151582:7794:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;125620:224;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152886:181;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;108700:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109872:158;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109691:115;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;153500:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151642:35;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;153628:765;;;:::i;:::-;;151918:40;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;126264:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;157604:367;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;154401:1122;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;110541:588;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125928:260;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152108:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151684:42;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;157979:156;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;158313:110;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111200:134;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;159173:200;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;126445:231;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152017:45;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151787:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152172:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108513:120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;153264:228;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;152141:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152755:123;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;108238:213;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;134050:103;;;:::i;:::-;;153075:181;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;151733:47;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;133375:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;108860:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110102:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;158143:162;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111405:236;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;155789:1807;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151818:31;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110319:155;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;134308:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125620:224;125722:4;125761:35;125746:50;;;:11;:50;;;;:90;;;;125800:36;125824:11;125800:23;:36::i;:::-;125746:90;125739:97;;125620:224;;;:::o;152886:181::-;152700:8;;;;;;;;;;;152686:22;;:10;:22;;;152678:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;153014:10:::1;153002:9;:22;;;;153048:11;153035:10;:24;;;;152886:181:::0;;:::o;108700:91::-;108745:13;108778:5;108771:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108700:91;:::o;109872:158::-;109939:7;109959:22;109973:7;109959:13;:22::i;:::-;;110001:21;110014:7;110001:12;:21::i;:::-;109994:28;;109872:158;;;:::o;109691:115::-;109763:35;109772:2;109776:7;109785:12;:10;:12::i;:::-;109763:8;:35::i;:::-;109691:115;;:::o;153500:120::-;153565:4;153589:10;:23;153600:11;153589:23;;;;;;;;;;;;;;;;;;;;;;;;;153582:30;;153500:120;;;:::o;151642:35::-;;;;;;;;;;;;;:::o;153628:765::-;153688:10;153672:13;:11;:13::i;:::-;:26;153664:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;153752:1;153740:9;;:13;153732:45;;;;;;;;;;;;:::i;:::-;;;;;;;;;153827:20;;;;;;;;;;;153822:270;;153864:18;151779:1;153864:40;;153923:25;153937:10;153923:13;:25::i;:::-;153919:81;;;153983:1;153969:15;;;;;:::i;:::-;;;153919:81;154047:10;154022;:22;154033:10;154022:22;;;;;;;;;;;;;;;;:35;154014:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;153849:243;153822:270;154154:12;;;;;;;;;;;:25;;;154180:10;154200:4;154207:9;;154154:63;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154132:127;;;;;;;;;;;;:::i;:::-;;;;;;;;;154272:15;154290:19;:17;:19::i;:::-;154272:37;;154320:30;154330:10;154342:7;154320:9;:30::i;:::-;154361:10;:22;154372:10;154361:22;;;;;;;;;;;;;;;;:24;;;;;;;;;:::i;:::-;;;;;;153653:740;153628:765::o;151918:40::-;;;;;;;;;;;;;:::o;126264:104::-;126316:7;126343:10;:17;;;;126336:24;;126264:104;:::o;157604:367::-;157735:10;157715:30;;:16;157723:7;157715;:16::i;:::-;:30;;;157707:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;157798:12;;;;;;;;;;;:25;;;157824:10;157844:4;157851:10;;157798:64;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;157776:128;;;;;;;;;;;;:::i;:::-;;;;;;;;;157915:12;;;;;;;;;;;:25;;;157941:7;157950:12;157915:48;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;157604:367;;:::o;154401:1122::-;154471:1;154463:5;:9;154455:39;;;;;;;;;;;;:::i;:::-;;;;;;;;;154538:10;154529:5;154513:13;:11;:13::i;:::-;:21;;;;:::i;:::-;:35;;154505:66;;;;;;;;;;;;:::i;:::-;;;;;;;;;154655:20;;;;;;;;;;;154650:328;;154692:18;151779:1;154692:40;;154751:25;154765:10;154751:13;:25::i;:::-;154747:81;;;154811:1;154797:15;;;;;:::i;:::-;;;154747:81;154902:10;154893:5;154868:10;:22;154879:10;154868:22;;;;;;;;;;;;;;;;:30;;;;:::i;:::-;:44;;154842:124;;;;;;;;;;;;:::i;:::-;;;;;;;;;154677:301;154650:328;155039:18;155072:5;155060:9;;:17;;;;:::i;:::-;155039:38;;155110:12;;;;;;;;;;;:25;;;155136:10;155156:4;155163:10;155110:64;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;155088:128;;;;;;;;;;;;:::i;:::-;;;;;;;;;155276:9;155271:245;155295:5;155291:1;:9;155271:245;;;155322:15;155340:19;:17;:19::i;:::-;155322:37;;155374:30;155384:10;155396:7;155374:9;:30::i;:::-;155424:20;;;;;;;;;;;155419:86;;155465:10;:22;155476:10;155465:22;;;;;;;;;;;;;;;;:24;;;;;;;;;:::i;:::-;;;;;;155419:86;155307:209;155302:3;;;;;;;155271:245;;;;154444:1079;154401:1122;:::o;110541:588::-;110650:1;110636:16;;:2;:16;;;110632:89;;110706:1;110676:33;;;;;;;;;;;:::i;:::-;;;;;;;;110632:89;110942:21;110966:34;110974:2;110978:7;110987:12;:10;:12::i;:::-;110966:7;:34::i;:::-;110942:58;;111032:4;111015:21;;:13;:21;;;111011:111;;111081:4;111087:7;111096:13;111060:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;111011:111;110621:508;110541:588;;;:::o;125928:260::-;126016:7;126049:16;126059:5;126049:9;:16::i;:::-;126040:5;:25;126036:101;;126112:5;126119;126089:36;;;;;;;;;;;;:::i;:::-;;;;;;;;126036:101;126154:12;:19;126167:5;126154:19;;;;;;;;;;;;;;;:26;126174:5;126154:26;;;;;;;;;;;;126147:33;;125928:260;;;;:::o;152108:26::-;;;;;;;;;;;;;:::o;151684:42::-;;;:::o;157979:156::-;158059:10;158039:30;;:16;158047:7;158039;:16::i;:::-;:30;;;158031:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;158100:12;;;;;;;;;;;:18;;;158119:7;158100:27;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;157979:156;:::o;158313:110::-;152700:8;;;;;;;;;;;152686:22;;:10;:22;;;152678:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;158410:5:::1;158387:20;;:28;;;;;;;;;;;;;;;;;;158313:110:::0;:::o;111200:134::-;111287:39;111304:4;111310:2;111314:7;111287:39;;;;;;;;;;;;:16;:39::i;:::-;111200:134;;;:::o;159173:200::-;152700:8;;;;;;;;;;;152686:22;;:10;:22;;;152678:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;159278:1:::1;159252:28;;159260:5;159252:28;;::::0;159244:54:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;159309:5;:14;;;159324:8;;;;;;;;;;;159334:5;:15;;;159358:4;159334:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;159309:56;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;159173:200:::0;:::o;126445:231::-;126511:7;126544:13;:11;:13::i;:::-;126535:5;:22;126531:103;;126612:1;126616:5;126581:41;;;;;;;;;;;;:::i;:::-;;;;;;;;126531:103;126651:10;126662:5;126651:17;;;;;;;;:::i;:::-;;;;;;;;;;126644:24;;126445:231;;;:::o;152017:45::-;;;;;;;;;;;;;;;;;:::o;151787:24::-;;;;:::o;152172:25::-;;;;:::o;108513:120::-;108576:7;108603:22;108617:7;108603:13;:22::i;:::-;108596:29;;108513:120;;;:::o;153264:228::-;152700:8;;;;;;;;;;;152686:22;;:10;:22;;;152678:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;153379:9:::1;153374:111;153398:12;:19;153394:1;:23;153374:111;;;153469:4;153439:10;:27;153450:12;153463:1;153450:15;;;;;;;;:::i;:::-;;;;;;;;153439:27;;;;;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;153419:3;;;;;;;153374:111;;;;153264:228:::0;:::o;152141:24::-;;;;:::o;152755:123::-;152700:8;;;;;;;;;;;152686:22;;:10;:22;;;152678:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;152857:12:::1;152835;;:35;;;;;;;;;;;;;;;;;;152755:123:::0;:::o;108238:213::-;108301:7;108342:1;108325:19;;:5;:19;;;108321:89;;108395:1;108368:30;;;;;;;;;;;:::i;:::-;;;;;;;;108321:89;108427:9;:16;108437:5;108427:16;;;;;;;;;;;;;;;;108420:23;;108238:213;;;:::o;134050:103::-;133261:13;:11;:13::i;:::-;134115:30:::1;134142:1;134115:18;:30::i;:::-;134050:103::o:0;153075:181::-;152700:8;;;;;;;;;;;152686:22;;:10;:22;;;152678:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;153208:3:::1;153198:7;:13;;;;;;:::i;:::-;;153236:12;153222:11;:26;;;;;;:::i;:::-;;153075:181:::0;;:::o;151733:47::-;151779:1;151733:47;:::o;133375:87::-;133421:7;133448:6;;;;;;;;;;;133441:13;;133375:87;:::o;108860:95::-;108907:13;108940:7;108933:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108860:95;:::o;110102:146::-;110188:52;110207:12;:10;:12::i;:::-;110221:8;110231;110188:18;:52::i;:::-;110102:146;;:::o;158143:162::-;158226:10;158206:30;;:16;158214:7;158206;:16::i;:::-;:30;;;158198:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;158267:12;;;;;;;;;;;:21;;;158289:7;158267:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158143:162;:::o;111405:236::-;111519:31;111532:4;111538:2;111542:7;111519:12;:31::i;:::-;111561:72;111595:12;:10;:12::i;:::-;111609:4;111615:2;111619:7;111628:4;111561:33;:72::i;:::-;111405:236;;;;:::o;155789:1807::-;155890:13;155939:10;155929:7;:20;155921:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;156052:22;156115:7;156139:17;156148:7;156139:8;:17::i;:::-;156098:59;;;;;;;;;:::i;:::-;;;;;;;;;;;;;156052:116;;156179:25;156245:11;156269:17;156278:7;156269:8;:17::i;:::-;156228:59;;;;;;;;;:::i;:::-;;;;;;;;;;;;;156179:119;;156311:23;156375:7;156395:17;156404:7;156395:8;:17::i;:::-;156358:55;;;;;;;;;:::i;:::-;;;;;;;;;;;;;156311:113;;156435:20;156458:12;;;;;;;;;;;:22;;;156481:7;156458:31;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;156435:54;;156640:914;156817:17;156826:7;156817:8;:17::i;:::-;157032:8;157132:9;157230;157330:11;157429:6;156716:788;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;156640:13;:914::i;:::-;156547:1026;;;;;;;;:::i;:::-;;;;;;;;;;;;;156502:1086;;;;;;155789:1807;;;:::o;151818:31::-;;;;;;;;;;;;;:::o;110319:155::-;110407:4;110431:18;:25;110450:5;110431:25;;;;;;;;;;;;;;;:35;110457:8;110431:35;;;;;;;;;;;;;;;;;;;;;;;;;110424:42;;110319:155;;;;:::o;134308:220::-;133261:13;:11;:13::i;:::-;134413:1:::1;134393:22;;:8;:22;;::::0;134389:93:::1;;134467:1;134439:31;;;;;;;;;;;:::i;:::-;;;;;;;;134389:93;134492:28;134511:8;134492:18;:28::i;:::-;134308:220:::0;:::o;107869:305::-;107971:4;108023:25;108008:40;;;:11;:40;;;;:105;;;;108080:33;108065:48;;;:11;:48;;;;108008:105;:158;;;;108130:36;108154:11;108130:23;:36::i;:::-;108008:158;107988:178;;107869:305;;;:::o;122923:247::-;122986:7;123006:13;123022:17;123031:7;123022:8;:17::i;:::-;123006:33;;123071:1;123054:19;;:5;:19;;;123050:90;;123120:7;123097:31;;;;;;;;;;;:::i;:::-;;;;;;;;123050:90;123157:5;123150:12;;;122923:247;;;:::o;112404:129::-;112474:7;112501:15;:24;112517:7;112501:24;;;;;;;;;;;;;;;;;;;;;112494:31;;112404:129;;;:::o;18388:98::-;18441:7;18468:10;18461:17;;18388:98;:::o;121155:122::-;121236:33;121245:2;121249:7;121258:4;121264;121236:8;:33::i;:::-;121155:122;;;:::o;155531:250::-;155577:7;155617:1;155605:9;;:13;155597:36;;;;;;;;;;;;:::i;:::-;;;;;;;;;155644:13;155673:9;;155660:10;:22;;;;:::i;:::-;155644:38;;155693:15;155711;155720:5;155711:8;:15::i;:::-;155693:33;;155737:9;;:11;;;;;;;;;:::i;:::-;;;;;;155766:7;155759:14;;;;155531:250;:::o;117223:102::-;117291:26;117301:2;117305:7;117291:26;;;;;;;;;;;;:9;:26::i;:::-;117223:102;;:::o;126737:640::-;126832:7;126852:21;126876:32;126890:2;126894:7;126903:4;126876:13;:32::i;:::-;126852:56;;126950:1;126925:27;;:13;:27;;;126921:214;;126969:40;127001:7;126969:31;:40::i;:::-;126921:214;;;127048:2;127031:19;;:13;:19;;;127027:108;;127067:56;127100:13;127115:7;127067:32;:56::i;:::-;127027:108;126921:214;127163:1;127149:16;;:2;:16;;;127145:192;;127182:45;127219:7;127182:36;:45::i;:::-;127145:192;;;127266:2;127249:19;;:13;:19;;;127245:92;;127285:40;127313:2;127317:7;127285:27;:40::i;:::-;127245:92;127145:192;127356:13;127349:20;;;126737:640;;;;;:::o;133540:166::-;133611:12;:10;:12::i;:::-;133600:23;;:7;:5;:7::i;:::-;:23;;;133596:103;;133674:12;:10;:12::i;:::-;133647:40;;;;;;;;;;;:::i;:::-;;;;;;;;133596:103;133540:166::o;134688:191::-;134762:16;134781:6;;;;;;;;;;;134762:25;;134807:8;134798:6;;:17;;;;;;;;;;;;;;;;;;134862:8;134831:40;;134852:8;134831:40;;;;;;;;;;;;134751:128;134688:191;:::o;122362:318::-;122490:1;122470:22;;:8;:22;;;122466:93;;122538:8;122516:31;;;;;;;;;;;:::i;:::-;;;;;;;;122466:93;122607:8;122569:18;:25;122588:5;122569:25;;;;;;;;;;;;;;;:35;122595:8;122569:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;122653:8;122631:41;;122646:5;122631:41;;;122663:8;122631:41;;;;;;:::i;:::-;;;;;;;;122362:318;;;:::o;16738:948::-;16942:1;16925:2;:14;;;:18;16921:758;;;16980:2;16964:36;;;17001:8;17011:4;17017:7;17026:4;16964:67;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;16960:708;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17344:1;17327:6;:13;:18;17323:330;;17469:2;17433:39;;;;;;;;;;;:::i;:::-;;;;;;;;17323:330;17603:6;17597:13;17588:6;17584:2;17580:15;17573:38;16960:708;17089:41;;;17079:51;;;:6;:51;;;;17075:185;;17237:2;17201:39;;;;;;;;;;;:::i;:::-;;;;;;;;17075:185;17032:243;16921:758;16738:948;;;;;:::o;158627:506::-;158683:13;158722:1;158713:5;:10;158709:26;;158725:10;;;;;;;;;;;;;;;;;;;;;158709:26;158746:12;158761:5;158746:20;;158777:14;158802:78;158817:1;158809:4;:9;158802:78;;158835:8;;;;;:::i;:::-;;;;158866:2;158858:10;;;;;:::i;:::-;;;158802:78;;;158890:19;158922:6;158912:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158890:39;;158940:154;158956:1;158947:5;:10;158940:154;;158984:1;158974:11;;;;;:::i;:::-;;;159051:2;159043:5;:10;;;;:::i;:::-;159030:2;:24;;;;:::i;:::-;159017:39;;159000:6;159007;159000:14;;;;;;;;:::i;:::-;;;;;:56;;;;;;;;;;;159080:2;159071:11;;;;;:::i;:::-;;;158940:154;;;159118:6;159104:21;;;;;158627:506;;;;:::o;135590:126::-;135648:13;135681:27;135689:4;135695:6;;;;;;;;;;;;;;;;;135703:4;135681:7;:27::i;:::-;135674:34;;135590:126;;;:::o;106467:148::-;106543:4;106582:25;106567:40;;;:11;:40;;;;106560:47;;106467:148;;;:::o;112166:117::-;112232:7;112259;:16;112267:7;112259:16;;;;;;;;;;;;;;;;;;;;;112252:23;;112166:117;;;:::o;121465:678::-;121627:9;:31;;;;121656:1;121640:18;;:4;:18;;;;121627:31;121623:471;;;121675:13;121691:22;121705:7;121691:13;:22::i;:::-;121675:38;;121860:1;121844:18;;:4;:18;;;;:35;;;;;121875:4;121866:13;;:5;:13;;;;121844:35;:69;;;;;121884:29;121901:5;121908:4;121884:16;:29::i;:::-;121883:30;121844:69;121840:144;;;121963:4;121941:27;;;;;;;;;;;:::i;:::-;;;;;;;;121840:144;122004:9;122000:83;;;122059:7;122055:2;122039:28;;122048:5;122039:28;;;;;;;;;;;;122000:83;121660:434;121623:471;122133:2;122106:15;:24;122122:7;122106:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;121465:678;;;;:::o;158431:188::-;158487:7;158507:13;158523:4;158507:20;;158538:9;158573:1;158567;158559:5;:9;;;;:::i;:::-;158551:4;:18;;;;:::i;:::-;158550:24;;;;:::i;:::-;158538:36;;158606:5;158597;158593:1;:9;;;;:::i;:::-;158592:19;;;;:::i;:::-;158585:26;;;;158431:188;;;:::o;117552:210::-;117647:18;117653:2;117657:7;117647:5;:18::i;:::-;117676:78;117710:12;:10;:12::i;:::-;117732:1;117736:2;117740:7;117749:4;117676:33;:78::i;:::-;117552:210;;;:::o;115365:824::-;115451:7;115471:12;115486:17;115495:7;115486:8;:17::i;:::-;115471:32;;115582:1;115566:18;;:4;:18;;;115562:88;;115601:37;115618:4;115624;115630:7;115601:16;:37::i;:::-;115562:88;115713:1;115697:18;;:4;:18;;;115693:263;;115815:48;115832:1;115836:7;115853:1;115857:5;115815:8;:48::i;:::-;115928:1;115909:9;:15;115919:4;115909:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;115693:263;115986:1;115972:16;;:2;:16;;;115968:111;;116051:1;116034:9;:13;116044:2;116034:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;115968:111;116110:2;116091:7;:16;116099:7;116091:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;116149:7;116145:2;116130:27;;116139:4;116130:27;;;;;;;;;;;;116177:4;116170:11;;;115365:824;;;;;:::o;128097:164::-;128201:10;:17;;;;128174:15;:24;128190:7;128174:24;;;;;;;;;;;:44;;;;128229:10;128245:7;128229:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;128097:164;:::o;128888:1075::-;129154:22;129179:15;129189:4;129179:9;:15::i;:::-;129154:40;;129205:18;129226:17;:26;129244:7;129226:26;;;;;;;;;;;;129205:47;;129265:61;129329:12;:18;129342:4;129329:18;;;;;;;;;;;;;;;129265:82;;129468:14;129454:10;:28;129450:330;;129499:19;129521;:35;129541:14;129521:35;;;;;;;;;;;;129499:57;;129607:11;129573:19;:31;129593:10;129573:31;;;;;;;;;;;:45;;;;129724:10;129691:17;:30;129709:11;129691:30;;;;;;;;;;;:43;;;;129484:296;129450:330;129876:17;:26;129894:7;129876:26;;;;;;;;;;;129869:33;;;129920:19;:35;129940:14;129920:35;;;;;;;;;;;129913:42;;;128969:994;;;128888:1075;;:::o;130258:1079::-;130511:22;130556:1;130536:10;:17;;;;:21;;;;:::i;:::-;130511:46;;130568:18;130589:15;:24;130605:7;130589:24;;;;;;;;;;;;130568:45;;130940:19;130962:10;130973:14;130962:26;;;;;;;;:::i;:::-;;;;;;;;;;130940:48;;131026:11;131001:10;131012;131001:22;;;;;;;;:::i;:::-;;;;;;;;;:36;;;;131137:10;131106:15;:28;131122:11;131106:28;;;;;;;;;;;:41;;;;131278:15;:24;131294:7;131278:24;;;;;;;;;;;131271:31;;;131313:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;130329:1008;;;130258:1079;:::o;127678:218::-;127763:14;127796:1;127780:13;127790:2;127780:9;:13::i;:::-;:17;;;;:::i;:::-;127763:34;;127835:7;127808:12;:16;127821:2;127808:16;;;;;;;;;;;;;;;:24;127825:6;127808:24;;;;;;;;;;;:34;;;;127882:6;127853:17;:26;127871:7;127853:26;;;;;;;;;;;:35;;;;127752:144;127678:218;;:::o;136128:4109::-;136225:13;136477:1;136462:4;:11;:16;136458:31;;136480:9;;;;;;;;;;;;;;;;136458:31;137442:20;137465:11;:69;;137533:1;137528;137514:4;:11;137510:1;:15;;;;:::i;:::-;:19;;;;:::i;:::-;137509:25;;;;:::i;:::-;137465:69;;;137504:1;137499;137485:4;:11;:15;;;;:::i;:::-;137484:21;;;;:::i;:::-;137479:1;:27;;;;:::i;:::-;137465:69;137442:92;;137547:20;137581:12;137570:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;137547:47;;137746:1;137739:5;137735:13;137850:4;137842:6;137838:17;137884:4;137932;137926:11;137920:4;137916:22;138184:4;138176:6;138172:17;138227:8;138221:15;138267:4;138257:8;138250:22;138342:1286;138377:6;138368:7;138365:19;138342:1286;;;138483:1;138474:7;138470:15;138459:26;;138522:7;138516:14;139118:4;139110:5;139106:2;139102:14;139098:25;139088:8;139084:40;139078:47;139067:9;139059:67;139172:1;139161:9;139157:17;139144:30;;139264:4;139256:5;139252:2;139248:14;139244:25;139234:8;139230:40;139224:47;139213:9;139205:67;139318:1;139307:9;139303:17;139290:30;;139409:4;139401:5;139398:1;139394:13;139390:24;139380:8;139376:39;139370:46;139359:9;139351:66;139463:1;139452:9;139448:17;139435:30;;139546:4;139539:5;139535:16;139525:8;139521:31;139515:38;139504:9;139496:58;139600:1;139589:9;139585:17;139572:30;;138404:1224;138342:1286;;;139709:10;139699:8;139692:28;139739:11;139736:457;;;139924:1;139917:4;139911:11;139907:19;139949:1;139944:135;;;;140102:1;140097:81;;;;139900:278;;139944:135;140001:4;139997:1;139986:9;139982:17;139974:32;140055:4;140051:1;140040:9;140036:17;140028:32;139944:135;;140097:81;140154:4;140150:1;140139:9;140135:17;140127:32;139900:278;;139736:457;137632:2572;;;;;;140223:6;140216:13;;;;136128:4109;;;;;;:::o;116525:335::-;116607:1;116593:16;;:2;:16;;;116589:89;;116663:1;116633:33;;;;;;;;;;;:::i;:::-;;;;;;;;116589:89;116688:21;116712:32;116720:2;116724:7;116741:1;116712:7;:32::i;:::-;116688:56;;116784:1;116759:27;;:13;:27;;;116755:98;;116838:1;116810:31;;;;;;;;;;;:::i;:::-;;;;;;;;116755:98;116578:282;116525:335;;:::o;113572:376::-;113685:38;113699:5;113706:7;113715;113685:13;:38::i;:::-;113680:261;;113761:1;113744:19;;:5;:19;;;113740:190;;113814:7;113791:31;;;;;;;;;;;:::i;:::-;;;;;;;;113740:190;113897:7;113906;113870:44;;;;;;;;;;;;:::i;:::-;;;;;;;;113680:261;113572:376;;;:::o;112853:276::-;112956:4;113012:1;112993:21;;:7;:21;;;;:128;;;;;113041:7;113032:16;;:5;:16;;;:52;;;;113052:32;113069:5;113076:7;113052:16;:32::i;:::-;113032:52;:88;;;;113113:7;113088:32;;:21;113101:7;113088:12;:21::i;:::-;:32;;;113032:88;112993:128;112973:148;;112853:276;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:77::-;1555:7;1584:5;1573:16;;1518:77;;;:::o;1601:122::-;1674:24;1692:5;1674:24;:::i;:::-;1667:5;1664:35;1654:63;;1713:1;1710;1703:12;1654:63;1601:122;:::o;1729:139::-;1775:5;1813:6;1800:20;1791:29;;1829:33;1856:5;1829:33;:::i;:::-;1729:139;;;;:::o;1874:474::-;1942:6;1950;1999:2;1987:9;1978:7;1974:23;1970:32;1967:119;;;2005:79;;:::i;:::-;1967:119;2125:1;2150:53;2195:7;2186:6;2175:9;2171:22;2150:53;:::i;:::-;2140:63;;2096:117;2252:2;2278:53;2323:7;2314:6;2303:9;2299:22;2278:53;:::i;:::-;2268:63;;2223:118;1874:474;;;;;:::o;2354:99::-;2406:6;2440:5;2434:12;2424:22;;2354:99;;;:::o;2459:169::-;2543:11;2577:6;2572:3;2565:19;2617:4;2612:3;2608:14;2593:29;;2459:169;;;;:::o;2634:139::-;2723:6;2718:3;2713;2707:23;2764:1;2755:6;2750:3;2746:16;2739:27;2634:139;;;:::o;2779:102::-;2820:6;2871:2;2867:7;2862:2;2855:5;2851:14;2847:28;2837:38;;2779:102;;;:::o;2887:377::-;2975:3;3003:39;3036:5;3003:39;:::i;:::-;3058:71;3122:6;3117:3;3058:71;:::i;:::-;3051:78;;3138:65;3196:6;3191:3;3184:4;3177:5;3173:16;3138:65;:::i;:::-;3228:29;3250:6;3228:29;:::i;:::-;3223:3;3219:39;3212:46;;2979:285;2887:377;;;;:::o;3270:313::-;3383:4;3421:2;3410:9;3406:18;3398:26;;3470:9;3464:4;3460:20;3456:1;3445:9;3441:17;3434:47;3498:78;3571:4;3562:6;3498:78;:::i;:::-;3490:86;;3270:313;;;;:::o;3589:329::-;3648:6;3697:2;3685:9;3676:7;3672:23;3668:32;3665:119;;;3703:79;;:::i;:::-;3665:119;3823:1;3848:53;3893:7;3884:6;3873:9;3869:22;3848:53;:::i;:::-;3838:63;;3794:117;3589:329;;;;:::o;3924:126::-;3961:7;4001:42;3994:5;3990:54;3979:65;;3924:126;;;:::o;4056:96::-;4093:7;4122:24;4140:5;4122:24;:::i;:::-;4111:35;;4056:96;;;:::o;4158:118::-;4245:24;4263:5;4245:24;:::i;:::-;4240:3;4233:37;4158:118;;:::o;4282:222::-;4375:4;4413:2;4402:9;4398:18;4390:26;;4426:71;4494:1;4483:9;4479:17;4470:6;4426:71;:::i;:::-;4282:222;;;;:::o;4510:122::-;4583:24;4601:5;4583:24;:::i;:::-;4576:5;4573:35;4563:63;;4622:1;4619;4612:12;4563:63;4510:122;:::o;4638:139::-;4684:5;4722:6;4709:20;4700:29;;4738:33;4765:5;4738:33;:::i;:::-;4638:139;;;;:::o;4783:474::-;4851:6;4859;4908:2;4896:9;4887:7;4883:23;4879:32;4876:119;;;4914:79;;:::i;:::-;4876:119;5034:1;5059:53;5104:7;5095:6;5084:9;5080:22;5059:53;:::i;:::-;5049:63;;5005:117;5161:2;5187:53;5232:7;5223:6;5212:9;5208:22;5187:53;:::i;:::-;5177:63;;5132:118;4783:474;;;;;:::o;5263:329::-;5322:6;5371:2;5359:9;5350:7;5346:23;5342:32;5339:119;;;5377:79;;:::i;:::-;5339:119;5497:1;5522:53;5567:7;5558:6;5547:9;5543:22;5522:53;:::i;:::-;5512:63;;5468:117;5263:329;;;;:::o;5598:60::-;5626:3;5647:5;5640:12;;5598:60;;;:::o;5664:142::-;5714:9;5747:53;5765:34;5774:24;5792:5;5774:24;:::i;:::-;5765:34;:::i;:::-;5747:53;:::i;:::-;5734:66;;5664:142;;;:::o;5812:126::-;5862:9;5895:37;5926:5;5895:37;:::i;:::-;5882:50;;5812:126;;;:::o;5944:150::-;6018:9;6051:37;6082:5;6051:37;:::i;:::-;6038:50;;5944:150;;;:::o;6100:179::-;6211:61;6266:5;6211:61;:::i;:::-;6206:3;6199:74;6100:179;;:::o;6285:270::-;6402:4;6440:2;6429:9;6425:18;6417:26;;6453:95;6545:1;6534:9;6530:17;6521:6;6453:95;:::i;:::-;6285:270;;;;:::o;6561:118::-;6648:24;6666:5;6648:24;:::i;:::-;6643:3;6636:37;6561:118;;:::o;6685:222::-;6778:4;6816:2;6805:9;6801:18;6793:26;;6829:71;6897:1;6886:9;6882:17;6873:6;6829:71;:::i;:::-;6685:222;;;;:::o;6913:117::-;7022:1;7019;7012:12;7036:117;7145:1;7142;7135:12;7159:180;7207:77;7204:1;7197:88;7304:4;7301:1;7294:15;7328:4;7325:1;7318:15;7345:281;7428:27;7450:4;7428:27;:::i;:::-;7420:6;7416:40;7558:6;7546:10;7543:22;7522:18;7510:10;7507:34;7504:62;7501:88;;;7569:18;;:::i;:::-;7501:88;7609:10;7605:2;7598:22;7388:238;7345:281;;:::o;7632:129::-;7666:6;7693:20;;:::i;:::-;7683:30;;7722:33;7750:4;7742:6;7722:33;:::i;:::-;7632:129;;;:::o;7767:307::-;7828:4;7918:18;7910:6;7907:30;7904:56;;;7940:18;;:::i;:::-;7904:56;7978:29;8000:6;7978:29;:::i;:::-;7970:37;;8062:4;8056;8052:15;8044:23;;7767:307;;;:::o;8080:148::-;8178:6;8173:3;8168;8155:30;8219:1;8210:6;8205:3;8201:16;8194:27;8080:148;;;:::o;8234:423::-;8311:5;8336:65;8352:48;8393:6;8352:48;:::i;:::-;8336:65;:::i;:::-;8327:74;;8424:6;8417:5;8410:21;8462:4;8455:5;8451:16;8500:3;8491:6;8486:3;8482:16;8479:25;8476:112;;;8507:79;;:::i;:::-;8476:112;8597:54;8644:6;8639:3;8634;8597:54;:::i;:::-;8317:340;8234:423;;;;;:::o;8676:338::-;8731:5;8780:3;8773:4;8765:6;8761:17;8757:27;8747:122;;8788:79;;:::i;:::-;8747:122;8905:6;8892:20;8930:78;9004:3;8996:6;8989:4;8981:6;8977:17;8930:78;:::i;:::-;8921:87;;8737:277;8676:338;;;;:::o;9020:652::-;9097:6;9105;9154:2;9142:9;9133:7;9129:23;9125:32;9122:119;;;9160:79;;:::i;:::-;9122:119;9280:1;9305:53;9350:7;9341:6;9330:9;9326:22;9305:53;:::i;:::-;9295:63;;9251:117;9435:2;9424:9;9420:18;9407:32;9466:18;9458:6;9455:30;9452:117;;;9488:79;;:::i;:::-;9452:117;9593:62;9647:7;9638:6;9627:9;9623:22;9593:62;:::i;:::-;9583:72;;9378:287;9020:652;;;;;:::o;9678:619::-;9755:6;9763;9771;9820:2;9808:9;9799:7;9795:23;9791:32;9788:119;;;9826:79;;:::i;:::-;9788:119;9946:1;9971:53;10016:7;10007:6;9996:9;9992:22;9971:53;:::i;:::-;9961:63;;9917:117;10073:2;10099:53;10144:7;10135:6;10124:9;10120:22;10099:53;:::i;:::-;10089:63;;10044:118;10201:2;10227:53;10272:7;10263:6;10252:9;10248:22;10227:53;:::i;:::-;10217:63;;10172:118;9678:619;;;;;:::o;10303:141::-;10368:9;10401:37;10432:5;10401:37;:::i;:::-;10388:50;;10303:141;;;:::o;10450:161::-;10552:52;10598:5;10552:52;:::i;:::-;10547:3;10540:65;10450:161;;:::o;10617:252::-;10725:4;10763:2;10752:9;10748:18;10740:26;;10776:86;10859:1;10848:9;10844:17;10835:6;10776:86;:::i;:::-;10617:252;;;;:::o;10875:116::-;10945:21;10960:5;10945:21;:::i;:::-;10938:5;10935:32;10925:60;;10981:1;10978;10971:12;10925:60;10875:116;:::o;10997:133::-;11040:5;11078:6;11065:20;11056:29;;11094:30;11118:5;11094:30;:::i;:::-;10997:133;;;;:::o;11136:323::-;11192:6;11241:2;11229:9;11220:7;11216:23;11212:32;11209:119;;;11247:79;;:::i;:::-;11209:119;11367:1;11392:50;11434:7;11425:6;11414:9;11410:22;11392:50;:::i;:::-;11382:60;;11338:114;11136:323;;;;:::o;11465:111::-;11517:7;11546:24;11564:5;11546:24;:::i;:::-;11535:35;;11465:111;;;:::o;11582:152::-;11670:39;11703:5;11670:39;:::i;:::-;11663:5;11660:50;11650:78;;11724:1;11721;11714:12;11650:78;11582:152;:::o;11740:169::-;11801:5;11839:6;11826:20;11817:29;;11855:48;11897:5;11855:48;:::i;:::-;11740:169;;;;:::o;11915:359::-;11989:6;12038:2;12026:9;12017:7;12013:23;12009:32;12006:119;;;12044:79;;:::i;:::-;12006:119;12164:1;12189:68;12249:7;12240:6;12229:9;12225:22;12189:68;:::i;:::-;12179:78;;12135:132;11915:359;;;;:::o;12280:311::-;12357:4;12447:18;12439:6;12436:30;12433:56;;;12469:18;;:::i;:::-;12433:56;12519:4;12511:6;12507:17;12499:25;;12579:4;12573;12569:15;12561:23;;12280:311;;;:::o;12597:117::-;12706:1;12703;12696:12;12737:710;12833:5;12858:81;12874:64;12931:6;12874:64;:::i;:::-;12858:81;:::i;:::-;12849:90;;12959:5;12988:6;12981:5;12974:21;13022:4;13015:5;13011:16;13004:23;;13075:4;13067:6;13063:17;13055:6;13051:30;13104:3;13096:6;13093:15;13090:122;;;13123:79;;:::i;:::-;13090:122;13238:6;13221:220;13255:6;13250:3;13247:15;13221:220;;;13330:3;13359:37;13392:3;13380:10;13359:37;:::i;:::-;13354:3;13347:50;13426:4;13421:3;13417:14;13410:21;;13297:144;13281:4;13276:3;13272:14;13265:21;;13221:220;;;13225:21;12839:608;;12737:710;;;;;:::o;13470:370::-;13541:5;13590:3;13583:4;13575:6;13571:17;13567:27;13557:122;;13598:79;;:::i;:::-;13557:122;13715:6;13702:20;13740:94;13830:3;13822:6;13815:4;13807:6;13803:17;13740:94;:::i;:::-;13731:103;;13547:293;13470:370;;;;:::o;13846:539::-;13930:6;13979:2;13967:9;13958:7;13954:23;13950:32;13947:119;;;13985:79;;:::i;:::-;13947:119;14133:1;14122:9;14118:17;14105:31;14163:18;14155:6;14152:30;14149:117;;;14185:79;;:::i;:::-;14149:117;14290:78;14360:7;14351:6;14340:9;14336:22;14290:78;:::i;:::-;14280:88;;14076:302;13846:539;;;;:::o;14391:308::-;14453:4;14543:18;14535:6;14532:30;14529:56;;;14565:18;;:::i;:::-;14529:56;14603:29;14625:6;14603:29;:::i;:::-;14595:37;;14687:4;14681;14677:15;14669:23;;14391:308;;;:::o;14705:425::-;14783:5;14808:66;14824:49;14866:6;14824:49;:::i;:::-;14808:66;:::i;:::-;14799:75;;14897:6;14890:5;14883:21;14935:4;14928:5;14924:16;14973:3;14964:6;14959:3;14955:16;14952:25;14949:112;;;14980:79;;:::i;:::-;14949:112;15070:54;15117:6;15112:3;15107;15070:54;:::i;:::-;14789:341;14705:425;;;;;:::o;15150:340::-;15206:5;15255:3;15248:4;15240:6;15236:17;15232:27;15222:122;;15263:79;;:::i;:::-;15222:122;15380:6;15367:20;15405:79;15480:3;15472:6;15465:4;15457:6;15453:17;15405:79;:::i;:::-;15396:88;;15212:278;15150:340;;;;:::o;15496:834::-;15584:6;15592;15641:2;15629:9;15620:7;15616:23;15612:32;15609:119;;;15647:79;;:::i;:::-;15609:119;15795:1;15784:9;15780:17;15767:31;15825:18;15817:6;15814:30;15811:117;;;15847:79;;:::i;:::-;15811:117;15952:63;16007:7;15998:6;15987:9;15983:22;15952:63;:::i;:::-;15942:73;;15738:287;16092:2;16081:9;16077:18;16064:32;16123:18;16115:6;16112:30;16109:117;;;16145:79;;:::i;:::-;16109:117;16250:63;16305:7;16296:6;16285:9;16281:22;16250:63;:::i;:::-;16240:73;;16035:288;15496:834;;;;;:::o;16336:468::-;16401:6;16409;16458:2;16446:9;16437:7;16433:23;16429:32;16426:119;;;16464:79;;:::i;:::-;16426:119;16584:1;16609:53;16654:7;16645:6;16634:9;16630:22;16609:53;:::i;:::-;16599:63;;16555:117;16711:2;16737:50;16779:7;16770:6;16759:9;16755:22;16737:50;:::i;:::-;16727:60;;16682:115;16336:468;;;;;:::o;16810:943::-;16905:6;16913;16921;16929;16978:3;16966:9;16957:7;16953:23;16949:33;16946:120;;;16985:79;;:::i;:::-;16946:120;17105:1;17130:53;17175:7;17166:6;17155:9;17151:22;17130:53;:::i;:::-;17120:63;;17076:117;17232:2;17258:53;17303:7;17294:6;17283:9;17279:22;17258:53;:::i;:::-;17248:63;;17203:118;17360:2;17386:53;17431:7;17422:6;17411:9;17407:22;17386:53;:::i;:::-;17376:63;;17331:118;17516:2;17505:9;17501:18;17488:32;17547:18;17539:6;17536:30;17533:117;;;17569:79;;:::i;:::-;17533:117;17674:62;17728:7;17719:6;17708:9;17704:22;17674:62;:::i;:::-;17664:72;;17459:287;16810:943;;;;;;;:::o;17759:104::-;17804:7;17833:24;17851:5;17833:24;:::i;:::-;17822:35;;17759:104;;;:::o;17869:142::-;17972:32;17998:5;17972:32;:::i;:::-;17967:3;17960:45;17869:142;;:::o;18017:254::-;18126:4;18164:2;18153:9;18149:18;18141:26;;18177:87;18261:1;18250:9;18246:17;18237:6;18177:87;:::i;:::-;18017:254;;;;:::o;18277:474::-;18345:6;18353;18402:2;18390:9;18381:7;18377:23;18373:32;18370:119;;;18408:79;;:::i;:::-;18370:119;18528:1;18553:53;18598:7;18589:6;18578:9;18574:22;18553:53;:::i;:::-;18543:63;;18499:117;18655:2;18681:53;18726:7;18717:6;18706:9;18702:22;18681:53;:::i;:::-;18671:63;;18626:118;18277:474;;;;;:::o;18757:164::-;18897:16;18893:1;18885:6;18881:14;18874:40;18757:164;:::o;18927:366::-;19069:3;19090:67;19154:2;19149:3;19090:67;:::i;:::-;19083:74;;19166:93;19255:3;19166:93;:::i;:::-;19284:2;19279:3;19275:12;19268:19;;18927:366;;;:::o;19299:419::-;19465:4;19503:2;19492:9;19488:18;19480:26;;19552:9;19546:4;19542:20;19538:1;19527:9;19523:17;19516:47;19580:131;19706:4;19580:131;:::i;:::-;19572:139;;19299:419;;;:::o;19724:180::-;19772:77;19769:1;19762:88;19869:4;19866:1;19859:15;19893:4;19890:1;19883:15;19910:320;19954:6;19991:1;19985:4;19981:12;19971:22;;20038:1;20032:4;20028:12;20059:18;20049:81;;20115:4;20107:6;20103:17;20093:27;;20049:81;20177:2;20169:6;20166:14;20146:18;20143:38;20140:84;;20196:18;;:::i;:::-;20140:84;19961:269;19910:320;;;:::o;20236:168::-;20376:20;20372:1;20364:6;20360:14;20353:44;20236:168;:::o;20410:366::-;20552:3;20573:67;20637:2;20632:3;20573:67;:::i;:::-;20566:74;;20649:93;20738:3;20649:93;:::i;:::-;20767:2;20762:3;20758:12;20751:19;;20410:366;;;:::o;20782:419::-;20948:4;20986:2;20975:9;20971:18;20963:26;;21035:9;21029:4;21025:20;21021:1;21010:9;21006:17;20999:47;21063:131;21189:4;21063:131;:::i;:::-;21055:139;;20782:419;;;:::o;21207:169::-;21347:21;21343:1;21335:6;21331:14;21324:45;21207:169;:::o;21382:366::-;21524:3;21545:67;21609:2;21604:3;21545:67;:::i;:::-;21538:74;;21621:93;21710:3;21621:93;:::i;:::-;21739:2;21734:3;21730:12;21723:19;;21382:366;;;:::o;21754:419::-;21920:4;21958:2;21947:9;21943:18;21935:26;;22007:9;22001:4;21997:20;21993:1;21982:9;21978:17;21971:47;22035:131;22161:4;22035:131;:::i;:::-;22027:139;;21754:419;;;:::o;22179:180::-;22227:77;22224:1;22217:88;22324:4;22321:1;22314:15;22348:4;22345:1;22338:15;22365:191;22405:3;22424:20;22442:1;22424:20;:::i;:::-;22419:25;;22458:20;22476:1;22458:20;:::i;:::-;22453:25;;22501:1;22498;22494:9;22487:16;;22522:3;22519:1;22516:10;22513:36;;;22529:18;;:::i;:::-;22513:36;22365:191;;;;:::o;22562:168::-;22702:20;22698:1;22690:6;22686:14;22679:44;22562:168;:::o;22736:366::-;22878:3;22899:67;22963:2;22958:3;22899:67;:::i;:::-;22892:74;;22975:93;23064:3;22975:93;:::i;:::-;23093:2;23088:3;23084:12;23077:19;;22736:366;;;:::o;23108:419::-;23274:4;23312:2;23301:9;23297:18;23289:26;;23361:9;23355:4;23351:20;23347:1;23336:9;23332:17;23325:47;23389:131;23515:4;23389:131;:::i;:::-;23381:139;;23108:419;;;:::o;23533:442::-;23682:4;23720:2;23709:9;23705:18;23697:26;;23733:71;23801:1;23790:9;23786:17;23777:6;23733:71;:::i;:::-;23814:72;23882:2;23871:9;23867:18;23858:6;23814:72;:::i;:::-;23896;23964:2;23953:9;23949:18;23940:6;23896:72;:::i;:::-;23533:442;;;;;;:::o;23981:137::-;24035:5;24066:6;24060:13;24051:22;;24082:30;24106:5;24082:30;:::i;:::-;23981:137;;;;:::o;24124:345::-;24191:6;24240:2;24228:9;24219:7;24215:23;24211:32;24208:119;;;24246:79;;:::i;:::-;24208:119;24366:1;24391:61;24444:7;24435:6;24424:9;24420:22;24391:61;:::i;:::-;24381:71;;24337:125;24124:345;;;;:::o;24475:164::-;24615:16;24611:1;24603:6;24599:14;24592:40;24475:164;:::o;24645:366::-;24787:3;24808:67;24872:2;24867:3;24808:67;:::i;:::-;24801:74;;24884:93;24973:3;24884:93;:::i;:::-;25002:2;24997:3;24993:12;24986:19;;24645:366;;;:::o;25017:419::-;25183:4;25221:2;25210:9;25206:18;25198:26;;25270:9;25264:4;25260:20;25256:1;25245:9;25241:17;25234:47;25298:131;25424:4;25298:131;:::i;:::-;25290:139;;25017:419;;;:::o;25442:233::-;25481:3;25504:24;25522:5;25504:24;:::i;:::-;25495:33;;25550:66;25543:5;25540:77;25537:103;;25620:18;;:::i;:::-;25537:103;25667:1;25660:5;25656:13;25649:20;;25442:233;;;:::o;25681:165::-;25821:17;25817:1;25809:6;25805:14;25798:41;25681:165;:::o;25852:366::-;25994:3;26015:67;26079:2;26074:3;26015:67;:::i;:::-;26008:74;;26091:93;26180:3;26091:93;:::i;:::-;26209:2;26204:3;26200:12;26193:19;;25852:366;;;:::o;26224:419::-;26390:4;26428:2;26417:9;26413:18;26405:26;;26477:9;26471:4;26467:20;26463:1;26452:9;26448:17;26441:47;26505:131;26631:4;26505:131;:::i;:::-;26497:139;;26224:419;;;:::o;26649:98::-;26700:6;26734:5;26728:12;26718:22;;26649:98;;;:::o;26753:168::-;26836:11;26870:6;26865:3;26858:19;26910:4;26905:3;26901:14;26886:29;;26753:168;;;;:::o;26927:373::-;27013:3;27041:38;27073:5;27041:38;:::i;:::-;27095:70;27158:6;27153:3;27095:70;:::i;:::-;27088:77;;27174:65;27232:6;27227:3;27220:4;27213:5;27209:16;27174:65;:::i;:::-;27264:29;27286:6;27264:29;:::i;:::-;27259:3;27255:39;27248:46;;27017:283;26927:373;;;;:::o;27306:419::-;27445:4;27483:2;27472:9;27468:18;27460:26;;27496:71;27564:1;27553:9;27549:17;27540:6;27496:71;:::i;:::-;27614:9;27608:4;27604:20;27599:2;27588:9;27584:18;27577:48;27642:76;27713:4;27704:6;27642:76;:::i;:::-;27634:84;;27306:419;;;;;:::o;27731:167::-;27871:19;27867:1;27859:6;27855:14;27848:43;27731:167;:::o;27904:366::-;28046:3;28067:67;28131:2;28126:3;28067:67;:::i;:::-;28060:74;;28143:93;28232:3;28143:93;:::i;:::-;28261:2;28256:3;28252:12;28245:19;;27904:366;;;:::o;28276:419::-;28442:4;28480:2;28469:9;28465:18;28457:26;;28529:9;28523:4;28519:20;28515:1;28504:9;28500:17;28493:47;28557:131;28683:4;28557:131;:::i;:::-;28549:139;;28276:419;;;:::o;28701:168::-;28841:20;28837:1;28829:6;28825:14;28818:44;28701:168;:::o;28875:366::-;29017:3;29038:67;29102:2;29097:3;29038:67;:::i;:::-;29031:74;;29114:93;29203:3;29114:93;:::i;:::-;29232:2;29227:3;29223:12;29216:19;;28875:366;;;:::o;29247:419::-;29413:4;29451:2;29440:9;29436:18;29428:26;;29500:9;29494:4;29490:20;29486:1;29475:9;29471:17;29464:47;29528:131;29654:4;29528:131;:::i;:::-;29520:139;;29247:419;;;:::o;29672:410::-;29712:7;29735:20;29753:1;29735:20;:::i;:::-;29730:25;;29769:20;29787:1;29769:20;:::i;:::-;29764:25;;29824:1;29821;29817:9;29846:30;29864:11;29846:30;:::i;:::-;29835:41;;30025:1;30016:7;30012:15;30009:1;30006:22;29986:1;29979:9;29959:83;29936:139;;30055:18;;:::i;:::-;29936:139;29720:362;29672:410;;;;:::o;30088:442::-;30237:4;30275:2;30264:9;30260:18;30252:26;;30288:71;30356:1;30345:9;30341:17;30332:6;30288:71;:::i;:::-;30369:72;30437:2;30426:9;30422:18;30413:6;30369:72;:::i;:::-;30451;30519:2;30508:9;30504:18;30495:6;30451:72;:::i;:::-;30088:442;;;;;;:::o;30536:332::-;30657:4;30695:2;30684:9;30680:18;30672:26;;30708:71;30776:1;30765:9;30761:17;30752:6;30708:71;:::i;:::-;30789:72;30857:2;30846:9;30842:18;30833:6;30789:72;:::i;:::-;30536:332;;;;;:::o;30874:163::-;31014:15;31010:1;31002:6;30998:14;30991:39;30874:163;:::o;31043:366::-;31185:3;31206:67;31270:2;31265:3;31206:67;:::i;:::-;31199:74;;31282:93;31371:3;31282:93;:::i;:::-;31400:2;31395:3;31391:12;31384:19;;31043:366;;;:::o;31415:419::-;31581:4;31619:2;31608:9;31604:18;31596:26;;31668:9;31662:4;31658:20;31654:1;31643:9;31639:17;31632:47;31696:131;31822:4;31696:131;:::i;:::-;31688:139;;31415:419;;;:::o;31840:143::-;31897:5;31928:6;31922:13;31913:22;;31944:33;31971:5;31944:33;:::i;:::-;31840:143;;;;:::o;31989:351::-;32059:6;32108:2;32096:9;32087:7;32083:23;32079:32;32076:119;;;32114:79;;:::i;:::-;32076:119;32234:1;32259:64;32315:7;32306:6;32295:9;32291:22;32259:64;:::i;:::-;32249:74;;32205:128;31989:351;;;;:::o;32346:134::-;32404:9;32437:37;32468:5;32437:37;:::i;:::-;32424:50;;32346:134;;;:::o;32486:147::-;32581:45;32620:5;32581:45;:::i;:::-;32576:3;32569:58;32486:147;;:::o;32639:348::-;32768:4;32806:2;32795:9;32791:18;32783:26;;32819:79;32895:1;32884:9;32880:17;32871:6;32819:79;:::i;:::-;32908:72;32976:2;32965:9;32961:18;32952:6;32908:72;:::i;:::-;32639:348;;;;;:::o;32993:180::-;33041:77;33038:1;33031:88;33138:4;33135:1;33128:15;33162:4;33159:1;33152:15;33179:141;33228:4;33251:3;33243:11;;33274:3;33271:1;33264:14;33308:4;33305:1;33295:18;33287:26;;33179:141;;;:::o;33326:93::-;33363:6;33410:2;33405;33398:5;33394:14;33390:23;33380:33;;33326:93;;;:::o;33425:107::-;33469:8;33519:5;33513:4;33509:16;33488:37;;33425:107;;;;:::o;33538:393::-;33607:6;33657:1;33645:10;33641:18;33680:97;33710:66;33699:9;33680:97;:::i;:::-;33798:39;33828:8;33817:9;33798:39;:::i;:::-;33786:51;;33870:4;33866:9;33859:5;33855:21;33846:30;;33919:4;33909:8;33905:19;33898:5;33895:30;33885:40;;33614:317;;33538:393;;;;;:::o;33937:142::-;33987:9;34020:53;34038:34;34047:24;34065:5;34047:24;:::i;:::-;34038:34;:::i;:::-;34020:53;:::i;:::-;34007:66;;33937:142;;;:::o;34085:75::-;34128:3;34149:5;34142:12;;34085:75;;;:::o;34166:269::-;34276:39;34307:7;34276:39;:::i;:::-;34337:91;34386:41;34410:16;34386:41;:::i;:::-;34378:6;34371:4;34365:11;34337:91;:::i;:::-;34331:4;34324:105;34242:193;34166:269;;;:::o;34441:73::-;34486:3;34441:73;:::o;34520:189::-;34597:32;;:::i;:::-;34638:65;34696:6;34688;34682:4;34638:65;:::i;:::-;34573:136;34520:189;;:::o;34715:186::-;34775:120;34792:3;34785:5;34782:14;34775:120;;;34846:39;34883:1;34876:5;34846:39;:::i;:::-;34819:1;34812:5;34808:13;34799:22;;34775:120;;;34715:186;;:::o;34907:543::-;35008:2;35003:3;35000:11;34997:446;;;35042:38;35074:5;35042:38;:::i;:::-;35126:29;35144:10;35126:29;:::i;:::-;35116:8;35112:44;35309:2;35297:10;35294:18;35291:49;;;35330:8;35315:23;;35291:49;35353:80;35409:22;35427:3;35409:22;:::i;:::-;35399:8;35395:37;35382:11;35353:80;:::i;:::-;35012:431;;34997:446;34907:543;;;:::o;35456:117::-;35510:8;35560:5;35554:4;35550:16;35529:37;;35456:117;;;;:::o;35579:169::-;35623:6;35656:51;35704:1;35700:6;35692:5;35689:1;35685:13;35656:51;:::i;:::-;35652:56;35737:4;35731;35727:15;35717:25;;35630:118;35579:169;;;;:::o;35753:295::-;35829:4;35975:29;36000:3;35994:4;35975:29;:::i;:::-;35967:37;;36037:3;36034:1;36030:11;36024:4;36021:21;36013:29;;35753:295;;;;:::o;36053:1395::-;36170:37;36203:3;36170:37;:::i;:::-;36272:18;36264:6;36261:30;36258:56;;;36294:18;;:::i;:::-;36258:56;36338:38;36370:4;36364:11;36338:38;:::i;:::-;36423:67;36483:6;36475;36469:4;36423:67;:::i;:::-;36517:1;36541:4;36528:17;;36573:2;36565:6;36562:14;36590:1;36585:618;;;;37247:1;37264:6;37261:77;;;37313:9;37308:3;37304:19;37298:26;37289:35;;37261:77;37364:67;37424:6;37417:5;37364:67;:::i;:::-;37358:4;37351:81;37220:222;36555:887;;36585:618;36637:4;36633:9;36625:6;36621:22;36671:37;36703:4;36671:37;:::i;:::-;36730:1;36744:208;36758:7;36755:1;36752:14;36744:208;;;36837:9;36832:3;36828:19;36822:26;36814:6;36807:42;36888:1;36880:6;36876:14;36866:24;;36935:2;36924:9;36920:18;36907:31;;36781:4;36778:1;36774:12;36769:17;;36744:208;;;36980:6;36971:7;36968:19;36965:179;;;37038:9;37033:3;37029:19;37023:26;37081:48;37123:4;37115:6;37111:17;37100:9;37081:48;:::i;:::-;37073:6;37066:64;36988:156;36965:179;37190:1;37186;37178:6;37174:14;37170:22;37164:4;37157:36;36592:611;;;36555:887;;36145:1303;;;36053:1395;;:::o;37454:170::-;37594:22;37590:1;37582:6;37578:14;37571:46;37454:170;:::o;37630:366::-;37772:3;37793:67;37857:2;37852:3;37793:67;:::i;:::-;37786:74;;37869:93;37958:3;37869:93;:::i;:::-;37987:2;37982:3;37978:12;37971:19;;37630:366;;;:::o;38002:419::-;38168:4;38206:2;38195:9;38191:18;38183:26;;38255:9;38249:4;38245:20;38241:1;38230:9;38226:17;38219:47;38283:131;38409:4;38283:131;:::i;:::-;38275:139;;38002:419;;;:::o;38427:148::-;38529:11;38566:3;38551:18;;38427:148;;;;:::o;38605:874::-;38708:3;38745:5;38739:12;38774:36;38800:9;38774:36;:::i;:::-;38826:89;38908:6;38903:3;38826:89;:::i;:::-;38819:96;;38946:1;38935:9;38931:17;38962:1;38957:166;;;;39137:1;39132:341;;;;38924:549;;38957:166;39041:4;39037:9;39026;39022:25;39017:3;39010:38;39103:6;39096:14;39089:22;39081:6;39077:35;39072:3;39068:45;39061:52;;38957:166;;39132:341;39199:38;39231:5;39199:38;:::i;:::-;39259:1;39273:154;39287:6;39284:1;39281:13;39273:154;;;39361:7;39355:14;39351:1;39346:3;39342:11;39335:35;39411:1;39402:7;39398:15;39387:26;;39309:4;39306:1;39302:12;39297:17;;39273:154;;;39456:6;39451:3;39447:16;39440:23;;39139:334;;38924:549;;38712:767;;38605:874;;;;:::o;39485:161::-;39625:13;39621:1;39613:6;39609:14;39602:37;39485:161;:::o;39652:402::-;39812:3;39833:85;39915:2;39910:3;39833:85;:::i;:::-;39826:92;;39927:93;40016:3;39927:93;:::i;:::-;40045:2;40040:3;40036:12;40029:19;;39652:402;;;:::o;40060:390::-;40166:3;40194:39;40227:5;40194:39;:::i;:::-;40249:89;40331:6;40326:3;40249:89;:::i;:::-;40242:96;;40347:65;40405:6;40400:3;40393:4;40386:5;40382:16;40347:65;:::i;:::-;40437:6;40432:3;40428:16;40421:23;;40170:280;40060:390;;;;:::o;40456:695::-;40734:3;40756:92;40844:3;40835:6;40756:92;:::i;:::-;40749:99;;40865:148;41009:3;40865:148;:::i;:::-;40858:155;;41030:95;41121:3;41112:6;41030:95;:::i;:::-;41023:102;;41142:3;41135:10;;40456:695;;;;;:::o;41157:157::-;41297:9;41293:1;41285:6;41281:14;41274:33;41157:157;:::o;41320:400::-;41480:3;41501:84;41583:1;41578:3;41501:84;:::i;:::-;41494:91;;41594:93;41683:3;41594:93;:::i;:::-;41712:1;41707:3;41703:11;41696:18;;41320:400;;;:::o;41726:695::-;42004:3;42026:92;42114:3;42105:6;42026:92;:::i;:::-;42019:99;;42135:148;42279:3;42135:148;:::i;:::-;42128:155;;42300:95;42391:3;42382:6;42300:95;:::i;:::-;42293:102;;42412:3;42405:10;;41726:695;;;;;:::o;42427:434::-;42516:5;42541:66;42557:49;42599:6;42557:49;:::i;:::-;42541:66;:::i;:::-;42532:75;;42630:6;42623:5;42616:21;42668:4;42661:5;42657:16;42706:3;42697:6;42692:3;42688:16;42685:25;42682:112;;;42713:79;;:::i;:::-;42682:112;42803:52;42848:6;42843:3;42838;42803:52;:::i;:::-;42522:339;42427:434;;;;;:::o;42881:355::-;42948:5;42997:3;42990:4;42982:6;42978:17;42974:27;42964:122;;43005:79;;:::i;:::-;42964:122;43115:6;43109:13;43140:90;43226:3;43218:6;43211:4;43203:6;43199:17;43140:90;:::i;:::-;43131:99;;42954:282;42881:355;;;;:::o;43242:524::-;43322:6;43371:2;43359:9;43350:7;43346:23;43342:32;43339:119;;;43377:79;;:::i;:::-;43339:119;43518:1;43507:9;43503:17;43497:24;43548:18;43540:6;43537:30;43534:117;;;43570:79;;:::i;:::-;43534:117;43675:74;43741:7;43732:6;43721:9;43717:22;43675:74;:::i;:::-;43665:84;;43468:291;43242:524;;;;:::o;43772:214::-;43912:66;43908:1;43900:6;43896:14;43889:90;43772:214;:::o;43992:402::-;44152:3;44173:85;44255:2;44250:3;44173:85;:::i;:::-;44166:92;;44267:93;44356:3;44267:93;:::i;:::-;44385:2;44380:3;44376:12;44369:19;;43992:402;;;:::o;44400:384::-;44540:66;44536:1;44528:6;44524:14;44517:90;44641:34;44636:2;44628:6;44624:15;44617:59;44710:66;44705:2;44697:6;44693:15;44686:91;44400:384;:::o;44790:402::-;44950:3;44971:85;45053:2;45048:3;44971:85;:::i;:::-;44964:92;;45065:93;45154:3;45065:93;:::i;:::-;45183:2;45178:3;45174:12;45167:19;;44790:402;;;:::o;45198:214::-;45338:66;45334:1;45326:6;45322:14;45315:90;45198:214;:::o;45418:400::-;45578:3;45599:84;45681:1;45676:3;45599:84;:::i;:::-;45592:91;;45692:93;45781:3;45692:93;:::i;:::-;45810:1;45805:3;45801:11;45794:18;;45418:400;;;:::o;45824:214::-;45964:66;45960:1;45952:6;45948:14;45941:90;45824:214;:::o;46044:402::-;46204:3;46225:85;46307:2;46302:3;46225:85;:::i;:::-;46218:92;;46319:93;46408:3;46319:93;:::i;:::-;46437:2;46432:3;46428:12;46421:19;;46044:402;;;:::o;46452:214::-;46592:66;46588:1;46580:6;46576:14;46569:90;46452:214;:::o;46672:402::-;46832:3;46853:85;46935:2;46930:3;46853:85;:::i;:::-;46846:92;;46947:93;47036:3;46947:93;:::i;:::-;47065:2;47060:3;47056:12;47049:19;;46672:402;;;:::o;47080:214::-;47220:66;47216:1;47208:6;47204:14;47197:90;47080:214;:::o;47300:402::-;47460:3;47481:85;47563:2;47558:3;47481:85;:::i;:::-;47474:92;;47575:93;47664:3;47575:93;:::i;:::-;47693:2;47688:3;47684:12;47677:19;;47300:402;;;:::o;47708:214::-;47848:66;47844:1;47836:6;47832:14;47825:90;47708:214;:::o;47928:402::-;48088:3;48109:85;48191:2;48186:3;48109:85;:::i;:::-;48102:92;;48203:93;48292:3;48203:93;:::i;:::-;48321:2;48316:3;48312:12;48305:19;;47928:402;;;:::o;48336:143::-;48472:3;48468:1;48460:6;48456:14;48449:27;48336:143;:::o;48481:384::-;48641:3;48658:84;48740:1;48735:3;48658:84;:::i;:::-;48651:91;;48747:93;48836:3;48747:93;:::i;:::-;48861:1;48856:3;48852:11;48845:18;;48481:384;;;:::o;48867:3139::-;50047:3;50065:148;50209:3;50065:148;:::i;:::-;50058:155;;50226:95;50317:3;50308:6;50226:95;:::i;:::-;50219:102;;50334:148;50478:3;50334:148;:::i;:::-;50327:155;;50495:148;50639:3;50495:148;:::i;:::-;50488:155;;50656:95;50747:3;50738:6;50656:95;:::i;:::-;50649:102;;50764:148;50908:3;50764:148;:::i;:::-;50757:155;;50925:95;51016:3;51007:6;50925:95;:::i;:::-;50918:102;;51033:148;51177:3;51033:148;:::i;:::-;51026:155;;51194:95;51285:3;51276:6;51194:95;:::i;:::-;51187:102;;51302:148;51446:3;51302:148;:::i;:::-;51295:155;;51463:95;51554:3;51545:6;51463:95;:::i;:::-;51456:102;;51571:148;51715:3;51571:148;:::i;:::-;51564:155;;51732:95;51823:3;51814:6;51732:95;:::i;:::-;51725:102;;51840:148;51984:3;51840:148;:::i;:::-;51833:155;;52001:3;51994:10;;48867:3139;;;;;;;;;:::o;52008:171::-;52144:31;52140:1;52132:6;52128:14;52121:55;52008:171;:::o;52181:386::-;52341:3;52358:85;52440:2;52435:3;52358:85;:::i;:::-;52351:92;;52448:93;52537:3;52448:93;:::i;:::-;52562:2;52557:3;52553:12;52546:19;;52181:386;;;:::o;52569:525::-;52802:3;52820:148;52964:3;52820:148;:::i;:::-;52813:155;;52981:95;53072:3;53063:6;52981:95;:::i;:::-;52974:102;;53089:3;53082:10;;52569:525;;;;:::o;53096:152::-;53232:12;53228:1;53220:6;53216:14;53209:36;53096:152;:::o;53250:350::-;53392:3;53409:67;53473:2;53468:3;53409:67;:::i;:::-;53402:74;;53481:93;53570:3;53481:93;:::i;:::-;53595:2;53590:3;53586:12;53579:19;;53250:350;;;:::o;53602:403::-;53768:4;53802:2;53791:9;53787:18;53779:26;;53847:9;53841:4;53837:20;53833:1;53822:9;53818:17;53811:47;53871:131;53997:4;53871:131;:::i;:::-;53863:139;;53602:403;;;:::o;54007:174::-;54047:4;54063:20;54081:1;54063:20;:::i;:::-;54058:25;;54093:20;54111:1;54093:20;:::i;:::-;54088:25;;54133:1;54130;54126:9;54118:17;;54153:1;54147:4;54144:11;54141:37;;;54158:18;;:::i;:::-;54141:37;54007:174;;;;:::o;54183:155::-;54222:3;54241:24;54259:5;54241:24;:::i;:::-;54232:33;;54283:4;54276:5;54273:15;54270:41;;54291:18;;:::i;:::-;54270:41;54334:1;54327:5;54323:13;54316:20;;54183:155;;;:::o;54340:612::-;54535:4;54569:3;54558:9;54554:19;54546:27;;54579:71;54647:1;54636:9;54632:17;54623:6;54579:71;:::i;:::-;54656:72;54724:2;54713:9;54709:18;54700:6;54656:72;:::i;:::-;54734;54802:2;54791:9;54787:18;54778:6;54734:72;:::i;:::-;54849:9;54843:4;54839:20;54834:2;54823:9;54819:18;54812:48;54873:76;54944:4;54935:6;54873:76;:::i;:::-;54865:84;;54340:612;;;;;;;:::o;54954:129::-;55010:5;55037:6;55031:13;55022:22;;55049:32;55075:5;55049:32;:::i;:::-;54954:129;;;;:::o;55085:325::-;55154:6;55199:2;55187:9;55178:7;55174:23;55170:32;55167:119;;;55205:79;;:::i;:::-;55167:119;55317:1;55338:63;55393:7;55384:6;55373:9;55369:22;55338:63;:::i;:::-;55328:73;;55292:115;55085:325;;;;:::o;55412:164::-;55456:77;55453:1;55446:88;55549:4;55546:1;55539:15;55569:4;55566:1;55559:15;55578:165;55618:1;55631:20;55649:1;55631:20;:::i;:::-;55626:25;;55661:20;55679:1;55661:20;:::i;:::-;55656:25;;55696:1;55686:35;;55701:18;;:::i;:::-;55686:35;55739:1;55736;55732:9;55727:14;;55578:165;;;;:::o;55745:156::-;55777:1;55790:20;55808:1;55790:20;:::i;:::-;55785:25;;55820:20;55838:1;55820:20;:::i;:::-;55815:25;;55855:1;55845:35;;55860:18;;:::i;:::-;55845:35;55897:1;55894;55890:9;55885:14;;55745:156;;;;:::o;55903:164::-;55947:77;55944:1;55937:88;56040:4;56037:1;56030:15;56060:4;56057:1;56050:15
Swarm Source
ipfs://da5b6f6052b5d02e9631e638043fa34b7ca3c422daf53eda1cce189bb7607ab5
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.