Source Code
Overview
MON Balance
MON Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 46 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Approval For... | 39356606 | 54 days ago | IN | 0 MON | 0.00832915 | ||||
| Set Approval For... | 38913339 | 56 days ago | IN | 0 MON | 0.00571822 | ||||
| Withdraw Funds | 38341057 | 58 days ago | IN | 0 MON | 0.00439752 | ||||
| Mint | 38186124 | 59 days ago | IN | 69 MON | 0.03151128 | ||||
| Set Approval For... | 37956793 | 60 days ago | IN | 0 MON | 0.00599056 | ||||
| Withdraw Funds | 37921975 | 60 days ago | IN | 0 MON | 0.00661398 | ||||
| Mint | 37882582 | 60 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37837091 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37806818 | 61 days ago | IN | 69 MON | 0.03166528 | ||||
| Mint | 37766485 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37749746 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37740560 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37738748 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Withdraw Funds | 37732814 | 61 days ago | IN | 0 MON | 0.15 | ||||
| Withdraw Funds | 37732644 | 61 days ago | IN | 0 MON | 0.15 | ||||
| Mint | 37732116 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37731322 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37730987 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37728525 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37723264 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37723164 | 61 days ago | IN | 69 MON | 0.03151006 | ||||
| Mint | 37722981 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37722758 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37721828 | 61 days ago | IN | 69 MON | 0.03151128 | ||||
| Mint | 37721806 | 61 days ago | IN | 69 MON | 0.03151128 |
Loading...
Loading
Contract Name:
MonadMascots
Compiler Version
v0.8.30+commit.73712a01
Contract Source Code (Solidity)
/**
*Submitted for verification at monadscan.com on 2025-11-24
*/
// SPDX-License-Identifier: MIT
// 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/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/introspection/IERC165.sol
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @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.4.0) (token/ERC721/IERC721.sol)
pragma solidity >=0.6.2;
/**
* @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.4.0) (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity >=0.6.2;
/**
* @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.4.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity >=0.5.0;
/**
* @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.4.0) (interfaces/draft-IERC6093.sol)
pragma solidity >=0.8.4;
/**
* @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.4.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 {IERC721Receiver-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(reason, 0x20), mload(reason))
}
}
}
}
}
}
// 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.3.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 Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
*/
function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
assembly ("memory-safe") {
low := add(a, b)
high := lt(low, a)
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
*/
function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// 512-bit multiply [high low] = 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 = high * 2²⁵⁶ + low.
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
low := mul(a, b)
high := sub(sub(mm, low), lt(mm, low))
}
}
/**
* @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
success = c >= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a - b;
success = c <= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a * b;
assembly ("memory-safe") {
// Only true when the multiplication doesn't overflow
// (c / a == b) || (a == 0)
success := or(eq(div(c, a), b), iszero(a))
}
// equivalent to: success ? c : 0
result = c * SafeCast.toUint(success);
}
}
/**
* @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 {
success = b > 0;
assembly ("memory-safe") {
// The `DIV` opcode returns zero when the denominator is 0.
result := div(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 {
success = b > 0;
assembly ("memory-safe") {
// The `MOD` opcode returns zero when the denominator is 0.
result := mod(a, b)
}
}
}
/**
* @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryAdd(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
*/
function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
(, uint256 result) = trySub(a, b);
return result;
}
/**
* @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryMul(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @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 {
(uint256 high, uint256 low) = mul512(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (high == 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 low / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= high) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [high low].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
high := sub(high, gt(remainder, low))
low := sub(low, 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 ("memory-safe") {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [high low] by twos.
low := div(low, 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 high into low.
low |= high * 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 high
// is no longer required.
result = low * 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 Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
*/
function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
if (high >= 1 << n) {
Panic.panic(Panic.UNDER_OVERFLOW);
}
return (high << (256 - n)) | (low >> n);
}
}
/**
* @dev Calculates x * y >> n with full precision, following the selected rounding direction.
*/
function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 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 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;
// Shifts value right by the current result and use it as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
assembly ("memory-safe") {
r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
}
}
/**
* @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 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}
/**
* @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.4.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;
uint256 private constant SPECIAL_CHARS_LOOKUP =
(1 << 0x08) | // backspace
(1 << 0x09) | // tab
(1 << 0x0a) | // newline
(1 << 0x0c) | // form feed
(1 << 0x0d) | // carriage return
(1 << 0x22) | // double quote
(1 << 0x5c); // backslash
/**
* @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(add(buffer, 0x20), 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-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 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-string-uint256-uint256} 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-string-uint256-uint256} 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-string} 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-string-uint256-uint256} 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 guarantees 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-string} 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-string} 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-string-uint256-uint256} 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 Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.
*
* WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.
*
* NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of
* RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode
* characters that are not in this range, but other tooling may provide different results.
*/
function escapeJSON(string memory input) internal pure returns (string memory) {
bytes memory buffer = bytes(input);
bytes memory output = new bytes(2 * buffer.length); // worst case scenario
uint256 outputLength = 0;
for (uint256 i; i < buffer.length; ++i) {
bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));
if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {
output[outputLength++] = "\\";
if (char == 0x08) output[outputLength++] = "b";
else if (char == 0x09) output[outputLength++] = "t";
else if (char == 0x0a) output[outputLength++] = "n";
else if (char == 0x0c) output[outputLength++] = "f";
else if (char == 0x0d) output[outputLength++] = "r";
else if (char == 0x5c) output[outputLength++] = "\\";
else if (char == 0x22) {
// solhint-disable-next-line quotes
output[outputLength++] = '"';
}
} else {
output[outputLength++] = char;
}
}
// write the actual length and deallocate unused memory
assembly ("memory-safe") {
mstore(output, outputLength)
mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))
}
return string(output);
}
/**
* @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(add(buffer, 0x20), offset))
}
}
}
// File: @openzeppelin/contracts/utils/introspection/ERC165.sol
// OpenZeppelin Contracts (last updated v5.4.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 {
/// @inheritdoc IERC165
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.4.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_;
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/// @inheritdoc IERC721
function balanceOf(address owner) public view virtual returns (uint256) {
if (owner == address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
/// @inheritdoc IERC721
function ownerOf(uint256 tokenId) public view virtual returns (address) {
return _requireOwned(tokenId);
}
/// @inheritdoc IERC721Metadata
function name() public view virtual returns (string memory) {
return _name;
}
/// @inheritdoc IERC721Metadata
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/// @inheritdoc IERC721Metadata
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 "";
}
/// @inheritdoc IERC721
function approve(address to, uint256 tokenId) public virtual {
_approve(to, tokenId, _msgSender());
}
/// @inheritdoc IERC721
function getApproved(uint256 tokenId) public view virtual returns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/// @inheritdoc IERC721
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/// @inheritdoc IERC721
function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
return _operatorApprovals[owner][operator];
}
/// @inheritdoc IERC721
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);
}
}
/// @inheritdoc IERC721
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/// @inheritdoc IERC721
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.4.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity >=0.6.2;
/**
* @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.4.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();
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/// @inheritdoc IERC721Enumerable
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
if (index >= balanceOf(owner)) {
revert ERC721OutOfBoundsIndex(owner, index);
}
return _ownedTokens[owner][index];
}
/// @inheritdoc IERC721Enumerable
function totalSupply() public view virtual returns (uint256) {
return _allTokens.length;
}
/// @inheritdoc IERC721Enumerable
function tokenByIndex(uint256 index) public view virtual returns (uint256) {
if (index >= totalSupply()) {
revert ERC721OutOfBoundsIndex(address(0), index);
}
return _allTokens[index];
}
/// @inheritdoc ERC721
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/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @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: @openzeppelin/contracts/utils/cryptography/ECDSA.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.20;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
/**
* @dev The signature derives the `address(0)`.
*/
error ECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
*/
error ECDSAInvalidSignatureLength(uint256 length);
/**
* @dev The signature has an S value that is in the upper half order.
*/
error ECDSAInvalidSignatureS(bytes32 s);
/**
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
* return address(0) without also returning an error description. Errors are documented using an enum (error type)
* and a bytes32 providing additional information about the error.
*
* If no error is returned, then the address can be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/
function tryRecover(
bytes32 hash,
bytes memory signature
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly ("memory-safe") {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
// We do not check for an overflow here since the shift operation results in 0 or 1.
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
*/
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}
// File: @openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol
// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)
pragma solidity ^0.8.20;
/**
* @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
*
* The library provides methods for generating a hash of a message that conforms to the
* https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
* specifications.
*/
library MessageHashUtils {
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing a bytes32 `messageHash` with
* `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
* hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.
*
* NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
* keccak256, although any bytes32 value can be safely used because the final digest will
* be re-hashed.
*
* See {ECDSA-recover}.
*/
function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
assembly ("memory-safe") {
mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
}
}
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing an arbitrary `message` with
* `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
* hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.
*
* See {ECDSA-recover}.
*/
function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
return
keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
}
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x00` (data with intended validator).
*
* The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
* `validator` address. Then hashing the result.
*
* See {ECDSA-recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(hex"19_00", validator, data));
}
/**
* @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.
*/
function toDataWithIntendedValidatorHash(
address validator,
bytes32 messageHash
) internal pure returns (bytes32 digest) {
assembly ("memory-safe") {
mstore(0x00, hex"19_00")
mstore(0x02, shl(96, validator))
mstore(0x16, messageHash)
digest := keccak256(0x00, 0x36)
}
}
/**
* @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).
*
* The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
* `\x19\x01` and hashing the result. It corresponds to the hash signed by the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
*
* See {ECDSA-recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(ptr, hex"19_01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
digest := keccak256(ptr, 0x42)
}
}
}
// File: @openzeppelin/contracts/utils/Pausable.sol
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
// File: mon.sol
pragma solidity ^0.8.23;
contract MonadMascots is ERC721Enumerable, Ownable, Pausable {
address public verifierAddress;
IERC20 public burnToken;
uint256 public burnAmount;
address public constant DEAD_ADDRESS = 0x000000000000000000000000000000000000dEaD;
bool public updatesFrozen;
uint256 public mintPrice; // Dynamic mint price (can be 0 for free)
// Mapping from token ID to URL (could be IPFS, Arweave, HTTP, etc.)
mapping(uint256 => string) private _tokenUrls;
constructor() ERC721("MonadMascot", "MM") Ownable(msg.sender) {
mintPrice = 69 ether;
}
function setBurnToken(address _burnToken) external onlyOwner {
require(!updatesFrozen, "Updates are frozen");
burnToken = IERC20(_burnToken);
}
function setBurnAmount(uint256 _burnAmount) external onlyOwner {
require(!updatesFrozen, "Updates are frozen");
burnAmount = _burnAmount;
}
function setMintPrice(uint256 _mintPrice) external onlyOwner {
require(!updatesFrozen, "Updates are frozen");
mintPrice = _mintPrice;
}
function setPaused(bool _paused) external onlyOwner {
if (_paused) {
_pause();
} else {
_unpause();
}
}
function mint(uint256 inputFid, string memory url, bytes memory signature) external payable {
require(bytes(url).length > 0, "URL cannot be empty");
require(verifierAddress == address(0) || _verifySignatureWithUrl(msg.sender, inputFid, url, signature), "Invalid signature");
require(!tokenMinted(inputFid), "Token already minted");
require(!paused(), "Minting is paused");
require(msg.value >= mintPrice, "Insufficient payment");
// Only burn tokens if we have enough balance
if (address(burnToken) != address(0) && burnToken.balanceOf(address(this)) >= burnAmount) {
burnToken.transfer(DEAD_ADDRESS, burnAmount);
}
_safeMint(msg.sender, inputFid);
_tokenUrls[inputFid] = url;
}
function tokenMinted(uint256 tokenId) internal view returns (bool) {
return _ownerOf(tokenId) != address(0);
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(tokenMinted(tokenId), "Token does not exist");
string memory url = _tokenUrls[tokenId];
require(bytes(url).length > 0, "URL not set for token");
string memory json = Base64.encode(bytes(string(abi.encodePacked(
'{"name": "MonadMascot ',
toString(tokenId),
'", "description": "MonadMascots are unique personalized mascots generated using Farcaster data for each user.", "image": "',
url,
'", "attributes": [{"trait_type": "Species", "value": "MonadMascot"}]}'
))));
return string(
abi.encodePacked(
"data:application/json;base64,",
json
)
);
}
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT license
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);
}
function setVerifierAddress(address _verifierAddress) external onlyOwner {
verifierAddress = _verifierAddress;
}
function _verifySignature(address minter, uint256 tokenId, bytes memory signature) internal view returns (bool) {
bytes32 messageHash = keccak256(abi.encodePacked(minter, "WPLT", tokenId));
bytes32 ethSignedMessageHash = MessageHashUtils.toEthSignedMessageHash(messageHash);
address recoveredSigner = ECDSA.recover(ethSignedMessageHash, signature);
return recoveredSigner == verifierAddress;
}
function _verifySignatureWithUrl(address minter, uint256 tokenId, string memory url, bytes memory signature) internal view returns (bool) {
bytes32 messageHash = keccak256(abi.encodePacked(minter, "WPLT", tokenId, url));
bytes32 ethSignedMessageHash = MessageHashUtils.toEthSignedMessageHash(messageHash);
address recoveredSigner = ECDSA.recover(ethSignedMessageHash, signature);
return recoveredSigner == verifierAddress;
}
function updateTokenUrl(uint256 tokenId, string memory url) external onlyOwner {
require(tokenMinted(tokenId), "Token does not exist");
_tokenUrls[tokenId] = url;
}
function withdrawFunds() external onlyOwner {
(bool success, ) = msg.sender.call{value: address(this).balance}("");
require(success, "Transfer failed");
}
}
/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <[email protected]>
library Base64 {
bytes internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/// @notice Encodes some bytes to the base64 representation
function encode(bytes memory data) internal pure returns (string memory) {
uint256 len = data.length;
if (len == 0) return "";
// multiply by 4/3 rounded up
uint256 encodedLen = 4 * ((len + 2) / 3);
// Add some extra buffer at the end
bytes memory result = new bytes(encodedLen + 32);
bytes memory table = TABLE;
assembly {
let tablePtr := add(table, 1)
let resultPtr := add(result, 32)
for {
let i := 0
} lt(i, len) {
} {
i := add(i, 3)
let input := and(mload(add(data, i)), 0xffffff)
let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
out := shl(8, out)
out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))
out := shl(8, out)
out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))
out := shl(8, out)
out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
out := shl(224, out)
mstore(resultPtr, out)
resultPtr := add(resultPtr, 4)
}
switch mod(len, 3)
case 1 {
mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
}
case 2 {
mstore(sub(resultPtr, 1), shl(248, 0x3d))
}
mstore(result, encodedLen)
}
return string(result);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"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":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEAD_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"burnAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"inputFid","type":"uint256"},{"internalType":"string","name":"url","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","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":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_burnAmount","type":"uint256"}],"name":"setBurnAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_burnToken","type":"address"}],"name":"setBurnToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_verifierAddress","type":"address"}],"name":"setVerifierAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"url","type":"string"}],"name":"updateTokenUrl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updatesFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"verifierAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561000f575f5ffd5b50336040518060400160405280600b81526020017f4d6f6e61644d6173636f740000000000000000000000000000000000000000008152506040518060400160405280600281526020017f4d4d000000000000000000000000000000000000000000000000000000000000815250815f908161008b9190610433565b50806001908161009b9190610433565b5050505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361010e575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016101059190610541565b60405180910390fd5b61011d8161013360201b60201c565b506803bd913e6c1df40000600f8190555061055a565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061027157607f821691505b6020821081036102845761028361022d565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026102e67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102ab565b6102f086836102ab565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61033461032f61032a84610308565b610311565b610308565b9050919050565b5f819050919050565b61034d8361031a565b6103616103598261033b565b8484546102b7565b825550505050565b5f5f905090565b610378610369565b610383818484610344565b505050565b5b818110156103a65761039b5f82610370565b600181019050610389565b5050565b601f8211156103eb576103bc8161028a565b6103c58461029c565b810160208510156103d4578190505b6103e86103e08561029c565b830182610388565b50505b505050565b5f82821c905092915050565b5f61040b5f19846008026103f0565b1980831691505092915050565b5f61042383836103fc565b9150826002028217905092915050565b61043c826101f6565b67ffffffffffffffff81111561045557610454610200565b5b61045f825461025a565b61046a8282856103aa565b5f60209050601f83116001811461049b575f8415610489578287015190505b6104938582610418565b8655506104fa565b601f1984166104a98661028a565b5f5b828110156104d0578489015182556001820191506020850194506020810190506104ab565b868310156104ed57848901516104e9601f8916826103fc565b8355505b6001600288020188555050505b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61052b82610502565b9050919050565b61053b81610521565b82525050565b5f6020820190506105545f830184610532565b92915050565b614603806105675f395ff3fe6080604052600436106101f8575f3560e01c80636817c76c1161010c578063c35879801161009f578063e985e9c51161006e578063e985e9c5146106f4578063f2fde38b14610730578063f4a0a52814610758578063f7bc440c14610780578063faa0a264146107a8576101f8565b8063c35879801461063e578063c4c85ae014610666578063c87b56dd14610690578063cc43f3d3146106cc576101f8565b80638da5cb5b116100db5780638da5cb5b1461059a57806395d89b41146105c4578063a22cb465146105ee578063b88d4fde14610616576101f8565b80636817c76c1461050257806370a082311461052c578063715018a614610568578063785cc9971461057e576101f8565b806323b872dd1161018f578063486a7e6b1161015e578063486a7e6b1461040c5780634e6fd6c4146104365780634f6ccce7146104605780635c975abb1461049c5780636352211e146104c6576101f8565b806323b872dd1461036a57806324600fc3146103925780632f745c59146103a857806342842e0e146103e4576101f8565b806316c38b3c116101cb57806316c38b3c146102c657806317e95526146102ee57806318160ddd1461031657806318bdffbb14610340576101f8565b806301ffc9a7146101fc57806306fdde0314610238578063081812fc14610262578063095ea7b31461029e575b5f5ffd5b348015610207575f5ffd5b50610222600480360381019061021d9190612fd7565b6107d2565b60405161022f919061301c565b60405180910390f35b348015610243575f5ffd5b5061024c61084b565b60405161025991906130a5565b60405180910390f35b34801561026d575f5ffd5b50610288600480360381019061028391906130f8565b6108da565b6040516102959190613162565b60405180910390f35b3480156102a9575f5ffd5b506102c460048036038101906102bf91906131a5565b6108f5565b005b3480156102d1575f5ffd5b506102ec60048036038101906102e7919061320d565b61090b565b005b3480156102f9575f5ffd5b50610314600480360381019061030f9190613238565b610932565b005b348015610321575f5ffd5b5061032a61097d565b6040516103379190613272565b60405180910390f35b34801561034b575f5ffd5b50610354610989565b6040516103619190613162565b60405180910390f35b348015610375575f5ffd5b50610390600480360381019061038b919061328b565b6109ae565b005b34801561039d575f5ffd5b506103a6610aad565b005b3480156103b3575f5ffd5b506103ce60048036038101906103c991906131a5565b610b60565b6040516103db9190613272565b60405180910390f35b3480156103ef575f5ffd5b5061040a6004803603810190610405919061328b565b610c04565b005b348015610417575f5ffd5b50610420610c23565b60405161042d9190613272565b60405180910390f35b348015610441575f5ffd5b5061044a610c29565b6040516104579190613162565b60405180910390f35b34801561046b575f5ffd5b50610486600480360381019061048191906130f8565b610c2f565b6040516104939190613272565b60405180910390f35b3480156104a7575f5ffd5b506104b0610ca1565b6040516104bd919061301c565b60405180910390f35b3480156104d1575f5ffd5b506104ec60048036038101906104e791906130f8565b610cb7565b6040516104f99190613162565b60405180910390f35b34801561050d575f5ffd5b50610516610cc8565b6040516105239190613272565b60405180910390f35b348015610537575f5ffd5b50610552600480360381019061054d9190613238565b610cce565b60405161055f9190613272565b60405180910390f35b348015610573575f5ffd5b5061057c610d84565b005b610598600480360381019061059391906134a5565b610d97565b005b3480156105a5575f5ffd5b506105ae61111e565b6040516105bb9190613162565b60405180910390f35b3480156105cf575f5ffd5b506105d8611146565b6040516105e591906130a5565b60405180910390f35b3480156105f9575f5ffd5b50610614600480360381019061060f919061352d565b6111d6565b005b348015610621575f5ffd5b5061063c6004803603810190610637919061356b565b6111ec565b005b348015610649575f5ffd5b50610664600480360381019061065f9190613238565b611211565b005b348015610671575f5ffd5b5061067a6112ab565b604051610687919061301c565b60405180910390f35b34801561069b575f5ffd5b506106b660048036038101906106b191906130f8565b6112bd565b6040516106c391906130a5565b60405180910390f35b3480156106d7575f5ffd5b506106f260048036038101906106ed91906130f8565b611443565b005b3480156106ff575f5ffd5b5061071a600480360381019061071591906135eb565b6114a4565b604051610727919061301c565b60405180910390f35b34801561073b575f5ffd5b5061075660048036038101906107519190613238565b611532565b005b348015610763575f5ffd5b5061077e600480360381019061077991906130f8565b6115b6565b005b34801561078b575f5ffd5b506107a660048036038101906107a19190613629565b611617565b005b3480156107b3575f5ffd5b506107bc61168a565b6040516107c991906136de565b60405180910390f35b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108445750610843826116af565b5b9050919050565b60605f805461085990613724565b80601f016020809104026020016040519081016040528092919081815260200182805461088590613724565b80156108d05780601f106108a7576101008083540402835291602001916108d0565b820191905f5260205f20905b8154815290600101906020018083116108b357829003601f168201915b5050505050905090565b5f6108e482611790565b506108ee82611816565b9050919050565b610907828261090261184f565b611856565b5050565b610913611868565b8015610926576109216118ef565b61092f565b61092e611952565b5b50565b61093a611868565b80600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f600880549050905090565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a1e575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401610a159190613162565b60405180910390fd5b5f610a318383610a2c61184f565b6119b4565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610aa7578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610a9e93929190613754565b60405180910390fd5b50505050565b610ab5611868565b5f3373ffffffffffffffffffffffffffffffffffffffff1647604051610ada906137b6565b5f6040518083038185875af1925050503d805f8114610b14576040519150601f19603f3d011682016040523d82523d5f602084013e610b19565b606091505b5050905080610b5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5490613814565b60405180910390fd5b50565b5f610b6a83610cce565b8210610baf5782826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610ba6929190613832565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b610c1e83838360405180602001604052805f8152506111ec565b505050565b600d5481565b61dead81565b5f610c3861097d565b8210610c7d575f826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610c74929190613832565b60405180910390fd5b60088281548110610c9157610c90613859565b5b905f5260205f2001549050919050565b5f600a60149054906101000a900460ff16905090565b5f610cc182611790565b9050919050565b600f5481565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d3f575f6040517f89c62b64000000000000000000000000000000000000000000000000000000008152600401610d369190613162565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b610d8c611868565b610d955f611ace565b565b5f825111610dda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dd1906138d0565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480610e3d5750610e3c33848484611b91565b5b610e7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7390613938565b60405180910390fd5b610e8583611c36565b15610ec5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ebc906139a0565b60405180910390fd5b610ecd610ca1565b15610f0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0490613a08565b60405180910390fd5b600f54341015610f52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4990613a70565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff16600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156110495750600d54600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016110079190613162565b602060405180830381865afa158015611022573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110469190613aa2565b10155b156110f057600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61dead600d546040518363ffffffff1660e01b81526004016110ae929190613832565b6020604051808303815f875af11580156110ca573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110ee9190613ae1565b505b6110fa3384611c76565b8160105f8581526020019081526020015f2090816111189190613ca3565b50505050565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606001805461115590613724565b80601f016020809104026020016040519081016040528092919081815260200182805461118190613724565b80156111cc5780601f106111a3576101008083540402835291602001916111cc565b820191905f5260205f20905b8154815290600101906020018083116111af57829003601f168201915b5050505050905090565b6111e86111e161184f565b8383611c93565b5050565b6111f78484846109ae565b61120b61120261184f565b85858585611dfc565b50505050565b611219611868565b600e5f9054906101000a900460ff1615611268576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161125f90613dbc565b60405180910390fd5b80600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600e5f9054906101000a900460ff1681565b60606112c882611c36565b611307576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fe90613e24565b60405180910390fd5b5f60105f8481526020019081526020015f20805461132490613724565b80601f016020809104026020016040519081016040528092919081815260200182805461135090613724565b801561139b5780601f106113725761010080835404028352916020019161139b565b820191905f5260205f20905b81548152906001019060200180831161137e57829003601f168201915b505050505090505f8151116113e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113dc90613e8c565b60405180910390fd5b5f6114186113f285611fa8565b83604051602001611404929190614080565b604051602081830303815290604052612101565b90508060405160200161142b919061410e565b60405160208183030381529060405292505050919050565b61144b611868565b600e5f9054906101000a900460ff161561149a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149190613dbc565b60405180910390fd5b80600d8190555050565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b61153a611868565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036115aa575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016115a19190613162565b60405180910390fd5b6115b381611ace565b50565b6115be611868565b600e5f9054906101000a900460ff161561160d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160490613dbc565b60405180910390fd5b80600f8190555050565b61161f611868565b61162882611c36565b611667576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161165e90613e24565b60405180910390fd5b8060105f8481526020019081526020015f2090816116859190613ca3565b505050565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061177957507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611789575061178882612291565b5b9050919050565b5f5f61179b836122fa565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361180d57826040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016118049190613272565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6118638383836001612333565b505050565b61187061184f565b73ffffffffffffffffffffffffffffffffffffffff1661188e61111e565b73ffffffffffffffffffffffffffffffffffffffff16146118ed576118b161184f565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016118e49190613162565b60405180910390fd5b565b6118f76124f2565b6001600a60146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861193b61184f565b6040516119489190613162565b60405180910390a1565b61195a612533565b5f600a60146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61199d61184f565b6040516119aa9190613162565b60405180910390a1565b5f5f6119c1858585612573565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a04576119ff8461277e565b611a43565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611a4257611a4181856127c2565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611a8457611a7f84612899565b611ac3565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611ac257611ac18585612959565b5b5b809150509392505050565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f5f858585604051602001611ba8939291906141de565b6040516020818303038152906040528051906020012090505f611bca826129dd565b90505f611bd78286612a10565b9050600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16149350505050949350505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff16611c57836122fa565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b611c8f828260405180602001604052805f815250612a3a565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d0357816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611cfa9190613162565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611def919061301c565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115611fa1578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b8152600401611e5a9493929190614273565b6020604051808303815f875af1925050508015611e9557506040513d601f19601f82011682018060405250810190611e9291906142d1565b60015b611f16573d805f8114611ec3576040519150601f19603f3d011682016040523d82523d5f602084013e611ec8565b606091505b505f815103611f0e57836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611f059190613162565b60405180910390fd5b805160208201fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611f9f57836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611f969190613162565b60405180910390fd5b505b5050505050565b60605f8203611fee576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506120fc565b5f8290505f5b5f821461201d57808061200690614329565b915050600a82612016919061439d565b9150611ff4565b5f8167ffffffffffffffff811115612038576120376132e3565b5b6040519080825280601f01601f19166020018201604052801561206a5781602001600182028036833780820191505090505b5090505b5f85146120f55760018261208291906143cd565b9150600a856120919190614400565b603061209d9190614430565b60f81b8183815181106120b3576120b2613859565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a856120ee919061439d565b945061206e565b8093505050505b919050565b60605f825190505f81036121265760405180602001604052805f81525091505061228c565b5f60036002836121369190614430565b612140919061439d565b600461214c9190614463565b90505f60208261215c9190614430565b67ffffffffffffffff811115612175576121746132e3565b5b6040519080825280601f01601f1916602001820160405280156121a75781602001600182028036833780820191505090505b5090505f60405180606001604052806040815260200161458e60409139905060018101602083015f5b868110156122495760038101905062ffffff818a015116603f8160121c168401518060081b905060ff603f83600c1c1686015116810190508060081b905060ff603f8360061c1686015116810190508060081b905060ff603f831686015116810190508060e01b905080845260048401935050506121d0565b50600386066001811461226357600281146122735761227e565b613d3d60f01b600283035261227e565b603d60f81b60018303525b508484525050819450505050505b919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061236b57505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b1561249d575f61237a84611790565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156123e457508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156123f757506123f581846114a4565b155b1561243957826040517fa9fbf51f0000000000000000000000000000000000000000000000000000000081526004016124309190613162565b60405180910390fd5b811561249b57838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b6124fa610ca1565b15612531576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61253b610ca1565b612571576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f5f61257e846122fa565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146125bf576125be818486612a5d565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461264a576125fe5f855f5f612333565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146126c957600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f6127cc83610cce565b90505f60075f8481526020019081526020015f205490505f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20905082821461286b575f815f8581526020019081526020015f2054905080825f8581526020019081526020015f20819055508260075f8381526020019081526020015f2081905550505b60075f8581526020019081526020015f205f9055805f8481526020019081526020015f205f90555050505050565b5f60016008805490506128ac91906143cd565b90505f60095f8481526020019081526020015f205490505f600883815481106128d8576128d7613859565b5b905f5260205f200154905080600883815481106128f8576128f7613859565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f905560088054806129405761293f6144a4565b5b600190038181905f5260205f20015f9055905550505050565b5f600161296584610cce565b61296f91906143cd565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b5f7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f5281601c52603c5f209050919050565b5f5f5f5f612a1e8686612b20565b925092509250612a2e8282612b75565b82935050505092915050565b612a448383612cd7565b612a58612a4f61184f565b5f858585611dfc565b505050565b612a68838383612dca565b612b1b575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612adc57806040517f7e273289000000000000000000000000000000000000000000000000000000008152600401612ad39190613272565b60405180910390fd5b81816040517f177e802f000000000000000000000000000000000000000000000000000000008152600401612b12929190613832565b60405180910390fd5b505050565b5f5f5f6041845103612b60575f5f5f602087015192506040870151915060608701515f1a9050612b5288828585612e8a565b955095509550505050612b6e565b5f600285515f1b9250925092505b9250925092565b5f6003811115612b8857612b876144d1565b5b826003811115612b9b57612b9a6144d1565b5b0315612cd35760016003811115612bb557612bb46144d1565b5b826003811115612bc857612bc76144d1565b5b03612bff576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612c1357612c126144d1565b5b826003811115612c2657612c256144d1565b5b03612c6a57805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401612c619190613272565b60405180910390fd5b600380811115612c7d57612c7c6144d1565b5b826003811115612c9057612c8f6144d1565b5b03612cd257806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612cc99190614516565b60405180910390fd5b5b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612d47575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612d3e9190613162565b60405180910390fd5b5f612d5383835f6119b4565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612dc5575f6040517f73c6ac6e000000000000000000000000000000000000000000000000000000008152600401612dbc9190613162565b60405180910390fd5b505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612e8157508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612e425750612e4184846114a4565b5b80612e8057508273ffffffffffffffffffffffffffffffffffffffff16612e6883611816565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f5f5f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115612ec6575f600385925092509250612f67565b5f6001888888886040515f8152602001604052604051612ee9949392919061454a565b6020604051602081039080840390855afa158015612f09573d5f5f3e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f5a575f60015f5f1b93509350935050612f67565b805f5f5f1b935093509350505b9450945094915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612fb681612f82565b8114612fc0575f5ffd5b50565b5f81359050612fd181612fad565b92915050565b5f60208284031215612fec57612feb612f7a565b5b5f612ff984828501612fc3565b91505092915050565b5f8115159050919050565b61301681613002565b82525050565b5f60208201905061302f5f83018461300d565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61307782613035565b613081818561303f565b935061309181856020860161304f565b61309a8161305d565b840191505092915050565b5f6020820190508181035f8301526130bd818461306d565b905092915050565b5f819050919050565b6130d7816130c5565b81146130e1575f5ffd5b50565b5f813590506130f2816130ce565b92915050565b5f6020828403121561310d5761310c612f7a565b5b5f61311a848285016130e4565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61314c82613123565b9050919050565b61315c81613142565b82525050565b5f6020820190506131755f830184613153565b92915050565b61318481613142565b811461318e575f5ffd5b50565b5f8135905061319f8161317b565b92915050565b5f5f604083850312156131bb576131ba612f7a565b5b5f6131c885828601613191565b92505060206131d9858286016130e4565b9150509250929050565b6131ec81613002565b81146131f6575f5ffd5b50565b5f81359050613207816131e3565b92915050565b5f6020828403121561322257613221612f7a565b5b5f61322f848285016131f9565b91505092915050565b5f6020828403121561324d5761324c612f7a565b5b5f61325a84828501613191565b91505092915050565b61326c816130c5565b82525050565b5f6020820190506132855f830184613263565b92915050565b5f5f5f606084860312156132a2576132a1612f7a565b5b5f6132af86828701613191565b93505060206132c086828701613191565b92505060406132d1868287016130e4565b9150509250925092565b5f5ffd5b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6133198261305d565b810181811067ffffffffffffffff82111715613338576133376132e3565b5b80604052505050565b5f61334a612f71565b90506133568282613310565b919050565b5f67ffffffffffffffff821115613375576133746132e3565b5b61337e8261305d565b9050602081019050919050565b828183375f83830152505050565b5f6133ab6133a68461335b565b613341565b9050828152602081018484840111156133c7576133c66132df565b5b6133d284828561338b565b509392505050565b5f82601f8301126133ee576133ed6132db565b5b81356133fe848260208601613399565b91505092915050565b5f67ffffffffffffffff821115613421576134206132e3565b5b61342a8261305d565b9050602081019050919050565b5f61344961344484613407565b613341565b905082815260208101848484011115613465576134646132df565b5b61347084828561338b565b509392505050565b5f82601f83011261348c5761348b6132db565b5b813561349c848260208601613437565b91505092915050565b5f5f5f606084860312156134bc576134bb612f7a565b5b5f6134c9868287016130e4565b935050602084013567ffffffffffffffff8111156134ea576134e9612f7e565b5b6134f6868287016133da565b925050604084013567ffffffffffffffff81111561351757613516612f7e565b5b61352386828701613478565b9150509250925092565b5f5f6040838503121561354357613542612f7a565b5b5f61355085828601613191565b9250506020613561858286016131f9565b9150509250929050565b5f5f5f5f6080858703121561358357613582612f7a565b5b5f61359087828801613191565b94505060206135a187828801613191565b93505060406135b2878288016130e4565b925050606085013567ffffffffffffffff8111156135d3576135d2612f7e565b5b6135df87828801613478565b91505092959194509250565b5f5f6040838503121561360157613600612f7a565b5b5f61360e85828601613191565b925050602061361f85828601613191565b9150509250929050565b5f5f6040838503121561363f5761363e612f7a565b5b5f61364c858286016130e4565b925050602083013567ffffffffffffffff81111561366d5761366c612f7e565b5b613679858286016133da565b9150509250929050565b5f819050919050565b5f6136a66136a161369c84613123565b613683565b613123565b9050919050565b5f6136b78261368c565b9050919050565b5f6136c8826136ad565b9050919050565b6136d8816136be565b82525050565b5f6020820190506136f15f8301846136cf565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061373b57607f821691505b60208210810361374e5761374d6136f7565b5b50919050565b5f6060820190506137675f830186613153565b6137746020830185613263565b6137816040830184613153565b949350505050565b5f81905092915050565b50565b5f6137a15f83613789565b91506137ac82613793565b5f82019050919050565b5f6137c082613796565b9150819050919050565b7f5472616e73666572206661696c656400000000000000000000000000000000005f82015250565b5f6137fe600f8361303f565b9150613809826137ca565b602082019050919050565b5f6020820190508181035f83015261382b816137f2565b9050919050565b5f6040820190506138455f830185613153565b6138526020830184613263565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f55524c2063616e6e6f7420626520656d707479000000000000000000000000005f82015250565b5f6138ba60138361303f565b91506138c582613886565b602082019050919050565b5f6020820190508181035f8301526138e7816138ae565b9050919050565b7f496e76616c6964207369676e61747572650000000000000000000000000000005f82015250565b5f61392260118361303f565b915061392d826138ee565b602082019050919050565b5f6020820190508181035f83015261394f81613916565b9050919050565b7f546f6b656e20616c7265616479206d696e7465640000000000000000000000005f82015250565b5f61398a60148361303f565b915061399582613956565b602082019050919050565b5f6020820190508181035f8301526139b78161397e565b9050919050565b7f4d696e74696e67206973207061757365640000000000000000000000000000005f82015250565b5f6139f260118361303f565b91506139fd826139be565b602082019050919050565b5f6020820190508181035f830152613a1f816139e6565b9050919050565b7f496e73756666696369656e74207061796d656e740000000000000000000000005f82015250565b5f613a5a60148361303f565b9150613a6582613a26565b602082019050919050565b5f6020820190508181035f830152613a8781613a4e565b9050919050565b5f81519050613a9c816130ce565b92915050565b5f60208284031215613ab757613ab6612f7a565b5b5f613ac484828501613a8e565b91505092915050565b5f81519050613adb816131e3565b92915050565b5f60208284031215613af657613af5612f7a565b5b5f613b0384828501613acd565b91505092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302613b687fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613b2d565b613b728683613b2d565b95508019841693508086168417925050509392505050565b5f613ba4613b9f613b9a846130c5565b613683565b6130c5565b9050919050565b5f819050919050565b613bbd83613b8a565b613bd1613bc982613bab565b848454613b39565b825550505050565b5f5f905090565b613be8613bd9565b613bf3818484613bb4565b505050565b5b81811015613c1657613c0b5f82613be0565b600181019050613bf9565b5050565b601f821115613c5b57613c2c81613b0c565b613c3584613b1e565b81016020851015613c44578190505b613c58613c5085613b1e565b830182613bf8565b50505b505050565b5f82821c905092915050565b5f613c7b5f1984600802613c60565b1980831691505092915050565b5f613c938383613c6c565b9150826002028217905092915050565b613cac82613035565b67ffffffffffffffff811115613cc557613cc46132e3565b5b613ccf8254613724565b613cda828285613c1a565b5f60209050601f831160018114613d0b575f8415613cf9578287015190505b613d038582613c88565b865550613d6a565b601f198416613d1986613b0c565b5f5b82811015613d4057848901518255600182019150602085019450602081019050613d1b565b86831015613d5d5784890151613d59601f891682613c6c565b8355505b6001600288020188555050505b505050505050565b7f55706461746573206172652066726f7a656e00000000000000000000000000005f82015250565b5f613da660128361303f565b9150613db182613d72565b602082019050919050565b5f6020820190508181035f830152613dd381613d9a565b9050919050565b7f546f6b656e20646f6573206e6f742065786973740000000000000000000000005f82015250565b5f613e0e60148361303f565b9150613e1982613dda565b602082019050919050565b5f6020820190508181035f830152613e3b81613e02565b9050919050565b7f55524c206e6f742073657420666f7220746f6b656e00000000000000000000005f82015250565b5f613e7660158361303f565b9150613e8182613e42565b602082019050919050565b5f6020820190508181035f830152613ea381613e6a565b9050919050565b5f81905092915050565b7f7b226e616d65223a20224d6f6e61644d6173636f7420000000000000000000005f82015250565b5f613ee8601683613eaa565b9150613ef382613eb4565b601682019050919050565b5f613f0882613035565b613f128185613eaa565b9350613f2281856020860161304f565b80840191505092915050565b7f222c20226465736372697074696f6e223a20224d6f6e61644d6173636f7473205f8201527f61726520756e6971756520706572736f6e616c697a6564206d6173636f74732060208201527f67656e657261746564207573696e67204661726361737465722064617461206660408201527f6f72206561636820757365722e222c2022696d616765223a2022000000000000606082015250565b5f613fd4607a83613eaa565b9150613fdf82613f2e565b607a82019050919050565b7f222c202261747472696275746573223a205b7b2274726169745f74797065223a5f8201527f202253706563696573222c202276616c7565223a20224d6f6e61644d6173636f60208201527f74227d5d7d000000000000000000000000000000000000000000000000000000604082015250565b5f61406a604583613eaa565b915061407582613fea565b604582019050919050565b5f61408a82613edc565b91506140968285613efe565b91506140a182613fc8565b91506140ad8284613efe565b91506140b88261405e565b91508190509392505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f6140f8601d83613eaa565b9150614103826140c4565b601d82019050919050565b5f614118826140ec565b91506141248284613efe565b915081905092915050565b5f8160601b9050919050565b5f6141458261412f565b9050919050565b5f6141568261413b565b9050919050565b61416e61416982613142565b61414c565b82525050565b7f57504c54000000000000000000000000000000000000000000000000000000005f82015250565b5f6141a8600483613eaa565b91506141b382614174565b600482019050919050565b5f819050919050565b6141d86141d3826130c5565b6141be565b82525050565b5f6141e9828661415d565b6014820191506141f88261419c565b915061420482856141c7565b6020820191506142148284613efe565b9150819050949350505050565b5f81519050919050565b5f82825260208201905092915050565b5f61424582614221565b61424f818561422b565b935061425f81856020860161304f565b6142688161305d565b840191505092915050565b5f6080820190506142865f830187613153565b6142936020830186613153565b6142a06040830185613263565b81810360608301526142b2818461423b565b905095945050505050565b5f815190506142cb81612fad565b92915050565b5f602082840312156142e6576142e5612f7a565b5b5f6142f3848285016142bd565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614333826130c5565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614365576143646142fc565b5b600182019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6143a7826130c5565b91506143b2836130c5565b9250826143c2576143c1614370565b5b828204905092915050565b5f6143d7826130c5565b91506143e2836130c5565b92508282039050818111156143fa576143f96142fc565b5b92915050565b5f61440a826130c5565b9150614415836130c5565b92508261442557614424614370565b5b828206905092915050565b5f61443a826130c5565b9150614445836130c5565b925082820190508082111561445d5761445c6142fc565b5b92915050565b5f61446d826130c5565b9150614478836130c5565b9250828202614486816130c5565b9150828204841483151761449d5761449c6142fc565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f819050919050565b614510816144fe565b82525050565b5f6020820190506145295f830184614507565b92915050565b5f60ff82169050919050565b6145448161452f565b82525050565b5f60808201905061455d5f830187614507565b61456a602083018661453b565b6145776040830185614507565b6145846060830184614507565b9594505050505056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122006acf36b1e4c2d87474a555bd7329253049a1f6cffcc07a326b894e304abd56b64736f6c634300081e0033
Deployed Bytecode
0x6080604052600436106101f8575f3560e01c80636817c76c1161010c578063c35879801161009f578063e985e9c51161006e578063e985e9c5146106f4578063f2fde38b14610730578063f4a0a52814610758578063f7bc440c14610780578063faa0a264146107a8576101f8565b8063c35879801461063e578063c4c85ae014610666578063c87b56dd14610690578063cc43f3d3146106cc576101f8565b80638da5cb5b116100db5780638da5cb5b1461059a57806395d89b41146105c4578063a22cb465146105ee578063b88d4fde14610616576101f8565b80636817c76c1461050257806370a082311461052c578063715018a614610568578063785cc9971461057e576101f8565b806323b872dd1161018f578063486a7e6b1161015e578063486a7e6b1461040c5780634e6fd6c4146104365780634f6ccce7146104605780635c975abb1461049c5780636352211e146104c6576101f8565b806323b872dd1461036a57806324600fc3146103925780632f745c59146103a857806342842e0e146103e4576101f8565b806316c38b3c116101cb57806316c38b3c146102c657806317e95526146102ee57806318160ddd1461031657806318bdffbb14610340576101f8565b806301ffc9a7146101fc57806306fdde0314610238578063081812fc14610262578063095ea7b31461029e575b5f5ffd5b348015610207575f5ffd5b50610222600480360381019061021d9190612fd7565b6107d2565b60405161022f919061301c565b60405180910390f35b348015610243575f5ffd5b5061024c61084b565b60405161025991906130a5565b60405180910390f35b34801561026d575f5ffd5b50610288600480360381019061028391906130f8565b6108da565b6040516102959190613162565b60405180910390f35b3480156102a9575f5ffd5b506102c460048036038101906102bf91906131a5565b6108f5565b005b3480156102d1575f5ffd5b506102ec60048036038101906102e7919061320d565b61090b565b005b3480156102f9575f5ffd5b50610314600480360381019061030f9190613238565b610932565b005b348015610321575f5ffd5b5061032a61097d565b6040516103379190613272565b60405180910390f35b34801561034b575f5ffd5b50610354610989565b6040516103619190613162565b60405180910390f35b348015610375575f5ffd5b50610390600480360381019061038b919061328b565b6109ae565b005b34801561039d575f5ffd5b506103a6610aad565b005b3480156103b3575f5ffd5b506103ce60048036038101906103c991906131a5565b610b60565b6040516103db9190613272565b60405180910390f35b3480156103ef575f5ffd5b5061040a6004803603810190610405919061328b565b610c04565b005b348015610417575f5ffd5b50610420610c23565b60405161042d9190613272565b60405180910390f35b348015610441575f5ffd5b5061044a610c29565b6040516104579190613162565b60405180910390f35b34801561046b575f5ffd5b50610486600480360381019061048191906130f8565b610c2f565b6040516104939190613272565b60405180910390f35b3480156104a7575f5ffd5b506104b0610ca1565b6040516104bd919061301c565b60405180910390f35b3480156104d1575f5ffd5b506104ec60048036038101906104e791906130f8565b610cb7565b6040516104f99190613162565b60405180910390f35b34801561050d575f5ffd5b50610516610cc8565b6040516105239190613272565b60405180910390f35b348015610537575f5ffd5b50610552600480360381019061054d9190613238565b610cce565b60405161055f9190613272565b60405180910390f35b348015610573575f5ffd5b5061057c610d84565b005b610598600480360381019061059391906134a5565b610d97565b005b3480156105a5575f5ffd5b506105ae61111e565b6040516105bb9190613162565b60405180910390f35b3480156105cf575f5ffd5b506105d8611146565b6040516105e591906130a5565b60405180910390f35b3480156105f9575f5ffd5b50610614600480360381019061060f919061352d565b6111d6565b005b348015610621575f5ffd5b5061063c6004803603810190610637919061356b565b6111ec565b005b348015610649575f5ffd5b50610664600480360381019061065f9190613238565b611211565b005b348015610671575f5ffd5b5061067a6112ab565b604051610687919061301c565b60405180910390f35b34801561069b575f5ffd5b506106b660048036038101906106b191906130f8565b6112bd565b6040516106c391906130a5565b60405180910390f35b3480156106d7575f5ffd5b506106f260048036038101906106ed91906130f8565b611443565b005b3480156106ff575f5ffd5b5061071a600480360381019061071591906135eb565b6114a4565b604051610727919061301c565b60405180910390f35b34801561073b575f5ffd5b5061075660048036038101906107519190613238565b611532565b005b348015610763575f5ffd5b5061077e600480360381019061077991906130f8565b6115b6565b005b34801561078b575f5ffd5b506107a660048036038101906107a19190613629565b611617565b005b3480156107b3575f5ffd5b506107bc61168a565b6040516107c991906136de565b60405180910390f35b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108445750610843826116af565b5b9050919050565b60605f805461085990613724565b80601f016020809104026020016040519081016040528092919081815260200182805461088590613724565b80156108d05780601f106108a7576101008083540402835291602001916108d0565b820191905f5260205f20905b8154815290600101906020018083116108b357829003601f168201915b5050505050905090565b5f6108e482611790565b506108ee82611816565b9050919050565b610907828261090261184f565b611856565b5050565b610913611868565b8015610926576109216118ef565b61092f565b61092e611952565b5b50565b61093a611868565b80600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f600880549050905090565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a1e575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401610a159190613162565b60405180910390fd5b5f610a318383610a2c61184f565b6119b4565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610aa7578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610a9e93929190613754565b60405180910390fd5b50505050565b610ab5611868565b5f3373ffffffffffffffffffffffffffffffffffffffff1647604051610ada906137b6565b5f6040518083038185875af1925050503d805f8114610b14576040519150601f19603f3d011682016040523d82523d5f602084013e610b19565b606091505b5050905080610b5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5490613814565b60405180910390fd5b50565b5f610b6a83610cce565b8210610baf5782826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610ba6929190613832565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b610c1e83838360405180602001604052805f8152506111ec565b505050565b600d5481565b61dead81565b5f610c3861097d565b8210610c7d575f826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610c74929190613832565b60405180910390fd5b60088281548110610c9157610c90613859565b5b905f5260205f2001549050919050565b5f600a60149054906101000a900460ff16905090565b5f610cc182611790565b9050919050565b600f5481565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d3f575f6040517f89c62b64000000000000000000000000000000000000000000000000000000008152600401610d369190613162565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b610d8c611868565b610d955f611ace565b565b5f825111610dda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dd1906138d0565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480610e3d5750610e3c33848484611b91565b5b610e7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7390613938565b60405180910390fd5b610e8583611c36565b15610ec5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ebc906139a0565b60405180910390fd5b610ecd610ca1565b15610f0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0490613a08565b60405180910390fd5b600f54341015610f52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4990613a70565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff16600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156110495750600d54600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016110079190613162565b602060405180830381865afa158015611022573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110469190613aa2565b10155b156110f057600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61dead600d546040518363ffffffff1660e01b81526004016110ae929190613832565b6020604051808303815f875af11580156110ca573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110ee9190613ae1565b505b6110fa3384611c76565b8160105f8581526020019081526020015f2090816111189190613ca3565b50505050565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606001805461115590613724565b80601f016020809104026020016040519081016040528092919081815260200182805461118190613724565b80156111cc5780601f106111a3576101008083540402835291602001916111cc565b820191905f5260205f20905b8154815290600101906020018083116111af57829003601f168201915b5050505050905090565b6111e86111e161184f565b8383611c93565b5050565b6111f78484846109ae565b61120b61120261184f565b85858585611dfc565b50505050565b611219611868565b600e5f9054906101000a900460ff1615611268576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161125f90613dbc565b60405180910390fd5b80600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600e5f9054906101000a900460ff1681565b60606112c882611c36565b611307576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fe90613e24565b60405180910390fd5b5f60105f8481526020019081526020015f20805461132490613724565b80601f016020809104026020016040519081016040528092919081815260200182805461135090613724565b801561139b5780601f106113725761010080835404028352916020019161139b565b820191905f5260205f20905b81548152906001019060200180831161137e57829003601f168201915b505050505090505f8151116113e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113dc90613e8c565b60405180910390fd5b5f6114186113f285611fa8565b83604051602001611404929190614080565b604051602081830303815290604052612101565b90508060405160200161142b919061410e565b60405160208183030381529060405292505050919050565b61144b611868565b600e5f9054906101000a900460ff161561149a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149190613dbc565b60405180910390fd5b80600d8190555050565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b61153a611868565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036115aa575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016115a19190613162565b60405180910390fd5b6115b381611ace565b50565b6115be611868565b600e5f9054906101000a900460ff161561160d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160490613dbc565b60405180910390fd5b80600f8190555050565b61161f611868565b61162882611c36565b611667576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161165e90613e24565b60405180910390fd5b8060105f8481526020019081526020015f2090816116859190613ca3565b505050565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061177957507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611789575061178882612291565b5b9050919050565b5f5f61179b836122fa565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361180d57826040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016118049190613272565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b6118638383836001612333565b505050565b61187061184f565b73ffffffffffffffffffffffffffffffffffffffff1661188e61111e565b73ffffffffffffffffffffffffffffffffffffffff16146118ed576118b161184f565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016118e49190613162565b60405180910390fd5b565b6118f76124f2565b6001600a60146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861193b61184f565b6040516119489190613162565b60405180910390a1565b61195a612533565b5f600a60146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61199d61184f565b6040516119aa9190613162565b60405180910390a1565b5f5f6119c1858585612573565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a04576119ff8461277e565b611a43565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611a4257611a4181856127c2565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611a8457611a7f84612899565b611ac3565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611ac257611ac18585612959565b5b5b809150509392505050565b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f5f858585604051602001611ba8939291906141de565b6040516020818303038152906040528051906020012090505f611bca826129dd565b90505f611bd78286612a10565b9050600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16149350505050949350505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff16611c57836122fa565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b611c8f828260405180602001604052805f815250612a3a565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611d0357816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611cfa9190613162565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611def919061301c565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115611fa1578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b8152600401611e5a9493929190614273565b6020604051808303815f875af1925050508015611e9557506040513d601f19601f82011682018060405250810190611e9291906142d1565b60015b611f16573d805f8114611ec3576040519150601f19603f3d011682016040523d82523d5f602084013e611ec8565b606091505b505f815103611f0e57836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611f059190613162565b60405180910390fd5b805160208201fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611f9f57836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611f969190613162565b60405180910390fd5b505b5050505050565b60605f8203611fee576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506120fc565b5f8290505f5b5f821461201d57808061200690614329565b915050600a82612016919061439d565b9150611ff4565b5f8167ffffffffffffffff811115612038576120376132e3565b5b6040519080825280601f01601f19166020018201604052801561206a5781602001600182028036833780820191505090505b5090505b5f85146120f55760018261208291906143cd565b9150600a856120919190614400565b603061209d9190614430565b60f81b8183815181106120b3576120b2613859565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a856120ee919061439d565b945061206e565b8093505050505b919050565b60605f825190505f81036121265760405180602001604052805f81525091505061228c565b5f60036002836121369190614430565b612140919061439d565b600461214c9190614463565b90505f60208261215c9190614430565b67ffffffffffffffff811115612175576121746132e3565b5b6040519080825280601f01601f1916602001820160405280156121a75781602001600182028036833780820191505090505b5090505f60405180606001604052806040815260200161458e60409139905060018101602083015f5b868110156122495760038101905062ffffff818a015116603f8160121c168401518060081b905060ff603f83600c1c1686015116810190508060081b905060ff603f8360061c1686015116810190508060081b905060ff603f831686015116810190508060e01b905080845260048401935050506121d0565b50600386066001811461226357600281146122735761227e565b613d3d60f01b600283035261227e565b603d60f81b60018303525b508484525050819450505050505b919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b808061236b57505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b1561249d575f61237a84611790565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156123e457508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156123f757506123f581846114a4565b155b1561243957826040517fa9fbf51f0000000000000000000000000000000000000000000000000000000081526004016124309190613162565b60405180910390fd5b811561249b57838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b6124fa610ca1565b15612531576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61253b610ca1565b612571576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f5f61257e846122fa565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146125bf576125be818486612a5d565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461264a576125fe5f855f5f612333565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146126c957600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f6127cc83610cce565b90505f60075f8481526020019081526020015f205490505f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20905082821461286b575f815f8581526020019081526020015f2054905080825f8581526020019081526020015f20819055508260075f8381526020019081526020015f2081905550505b60075f8581526020019081526020015f205f9055805f8481526020019081526020015f205f90555050505050565b5f60016008805490506128ac91906143cd565b90505f60095f8481526020019081526020015f205490505f600883815481106128d8576128d7613859565b5b905f5260205f200154905080600883815481106128f8576128f7613859565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f905560088054806129405761293f6144a4565b5b600190038181905f5260205f20015f9055905550505050565b5f600161296584610cce565b61296f91906143cd565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b5f7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f5281601c52603c5f209050919050565b5f5f5f5f612a1e8686612b20565b925092509250612a2e8282612b75565b82935050505092915050565b612a448383612cd7565b612a58612a4f61184f565b5f858585611dfc565b505050565b612a68838383612dca565b612b1b575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612adc57806040517f7e273289000000000000000000000000000000000000000000000000000000008152600401612ad39190613272565b60405180910390fd5b81816040517f177e802f000000000000000000000000000000000000000000000000000000008152600401612b12929190613832565b60405180910390fd5b505050565b5f5f5f6041845103612b60575f5f5f602087015192506040870151915060608701515f1a9050612b5288828585612e8a565b955095509550505050612b6e565b5f600285515f1b9250925092505b9250925092565b5f6003811115612b8857612b876144d1565b5b826003811115612b9b57612b9a6144d1565b5b0315612cd35760016003811115612bb557612bb46144d1565b5b826003811115612bc857612bc76144d1565b5b03612bff576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612c1357612c126144d1565b5b826003811115612c2657612c256144d1565b5b03612c6a57805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401612c619190613272565b60405180910390fd5b600380811115612c7d57612c7c6144d1565b5b826003811115612c9057612c8f6144d1565b5b03612cd257806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612cc99190614516565b60405180910390fd5b5b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612d47575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612d3e9190613162565b60405180910390fd5b5f612d5383835f6119b4565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612dc5575f6040517f73c6ac6e000000000000000000000000000000000000000000000000000000008152600401612dbc9190613162565b60405180910390fd5b505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015612e8157508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612e425750612e4184846114a4565b5b80612e8057508273ffffffffffffffffffffffffffffffffffffffff16612e6883611816565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f5f5f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115612ec6575f600385925092509250612f67565b5f6001888888886040515f8152602001604052604051612ee9949392919061454a565b6020604051602081039080840390855afa158015612f09573d5f5f3e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f5a575f60015f5f1b93509350935050612f67565b805f5f5f1b935093509350505b9450945094915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612fb681612f82565b8114612fc0575f5ffd5b50565b5f81359050612fd181612fad565b92915050565b5f60208284031215612fec57612feb612f7a565b5b5f612ff984828501612fc3565b91505092915050565b5f8115159050919050565b61301681613002565b82525050565b5f60208201905061302f5f83018461300d565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61307782613035565b613081818561303f565b935061309181856020860161304f565b61309a8161305d565b840191505092915050565b5f6020820190508181035f8301526130bd818461306d565b905092915050565b5f819050919050565b6130d7816130c5565b81146130e1575f5ffd5b50565b5f813590506130f2816130ce565b92915050565b5f6020828403121561310d5761310c612f7a565b5b5f61311a848285016130e4565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61314c82613123565b9050919050565b61315c81613142565b82525050565b5f6020820190506131755f830184613153565b92915050565b61318481613142565b811461318e575f5ffd5b50565b5f8135905061319f8161317b565b92915050565b5f5f604083850312156131bb576131ba612f7a565b5b5f6131c885828601613191565b92505060206131d9858286016130e4565b9150509250929050565b6131ec81613002565b81146131f6575f5ffd5b50565b5f81359050613207816131e3565b92915050565b5f6020828403121561322257613221612f7a565b5b5f61322f848285016131f9565b91505092915050565b5f6020828403121561324d5761324c612f7a565b5b5f61325a84828501613191565b91505092915050565b61326c816130c5565b82525050565b5f6020820190506132855f830184613263565b92915050565b5f5f5f606084860312156132a2576132a1612f7a565b5b5f6132af86828701613191565b93505060206132c086828701613191565b92505060406132d1868287016130e4565b9150509250925092565b5f5ffd5b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6133198261305d565b810181811067ffffffffffffffff82111715613338576133376132e3565b5b80604052505050565b5f61334a612f71565b90506133568282613310565b919050565b5f67ffffffffffffffff821115613375576133746132e3565b5b61337e8261305d565b9050602081019050919050565b828183375f83830152505050565b5f6133ab6133a68461335b565b613341565b9050828152602081018484840111156133c7576133c66132df565b5b6133d284828561338b565b509392505050565b5f82601f8301126133ee576133ed6132db565b5b81356133fe848260208601613399565b91505092915050565b5f67ffffffffffffffff821115613421576134206132e3565b5b61342a8261305d565b9050602081019050919050565b5f61344961344484613407565b613341565b905082815260208101848484011115613465576134646132df565b5b61347084828561338b565b509392505050565b5f82601f83011261348c5761348b6132db565b5b813561349c848260208601613437565b91505092915050565b5f5f5f606084860312156134bc576134bb612f7a565b5b5f6134c9868287016130e4565b935050602084013567ffffffffffffffff8111156134ea576134e9612f7e565b5b6134f6868287016133da565b925050604084013567ffffffffffffffff81111561351757613516612f7e565b5b61352386828701613478565b9150509250925092565b5f5f6040838503121561354357613542612f7a565b5b5f61355085828601613191565b9250506020613561858286016131f9565b9150509250929050565b5f5f5f5f6080858703121561358357613582612f7a565b5b5f61359087828801613191565b94505060206135a187828801613191565b93505060406135b2878288016130e4565b925050606085013567ffffffffffffffff8111156135d3576135d2612f7e565b5b6135df87828801613478565b91505092959194509250565b5f5f6040838503121561360157613600612f7a565b5b5f61360e85828601613191565b925050602061361f85828601613191565b9150509250929050565b5f5f6040838503121561363f5761363e612f7a565b5b5f61364c858286016130e4565b925050602083013567ffffffffffffffff81111561366d5761366c612f7e565b5b613679858286016133da565b9150509250929050565b5f819050919050565b5f6136a66136a161369c84613123565b613683565b613123565b9050919050565b5f6136b78261368c565b9050919050565b5f6136c8826136ad565b9050919050565b6136d8816136be565b82525050565b5f6020820190506136f15f8301846136cf565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061373b57607f821691505b60208210810361374e5761374d6136f7565b5b50919050565b5f6060820190506137675f830186613153565b6137746020830185613263565b6137816040830184613153565b949350505050565b5f81905092915050565b50565b5f6137a15f83613789565b91506137ac82613793565b5f82019050919050565b5f6137c082613796565b9150819050919050565b7f5472616e73666572206661696c656400000000000000000000000000000000005f82015250565b5f6137fe600f8361303f565b9150613809826137ca565b602082019050919050565b5f6020820190508181035f83015261382b816137f2565b9050919050565b5f6040820190506138455f830185613153565b6138526020830184613263565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f55524c2063616e6e6f7420626520656d707479000000000000000000000000005f82015250565b5f6138ba60138361303f565b91506138c582613886565b602082019050919050565b5f6020820190508181035f8301526138e7816138ae565b9050919050565b7f496e76616c6964207369676e61747572650000000000000000000000000000005f82015250565b5f61392260118361303f565b915061392d826138ee565b602082019050919050565b5f6020820190508181035f83015261394f81613916565b9050919050565b7f546f6b656e20616c7265616479206d696e7465640000000000000000000000005f82015250565b5f61398a60148361303f565b915061399582613956565b602082019050919050565b5f6020820190508181035f8301526139b78161397e565b9050919050565b7f4d696e74696e67206973207061757365640000000000000000000000000000005f82015250565b5f6139f260118361303f565b91506139fd826139be565b602082019050919050565b5f6020820190508181035f830152613a1f816139e6565b9050919050565b7f496e73756666696369656e74207061796d656e740000000000000000000000005f82015250565b5f613a5a60148361303f565b9150613a6582613a26565b602082019050919050565b5f6020820190508181035f830152613a8781613a4e565b9050919050565b5f81519050613a9c816130ce565b92915050565b5f60208284031215613ab757613ab6612f7a565b5b5f613ac484828501613a8e565b91505092915050565b5f81519050613adb816131e3565b92915050565b5f60208284031215613af657613af5612f7a565b5b5f613b0384828501613acd565b91505092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302613b687fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613b2d565b613b728683613b2d565b95508019841693508086168417925050509392505050565b5f613ba4613b9f613b9a846130c5565b613683565b6130c5565b9050919050565b5f819050919050565b613bbd83613b8a565b613bd1613bc982613bab565b848454613b39565b825550505050565b5f5f905090565b613be8613bd9565b613bf3818484613bb4565b505050565b5b81811015613c1657613c0b5f82613be0565b600181019050613bf9565b5050565b601f821115613c5b57613c2c81613b0c565b613c3584613b1e565b81016020851015613c44578190505b613c58613c5085613b1e565b830182613bf8565b50505b505050565b5f82821c905092915050565b5f613c7b5f1984600802613c60565b1980831691505092915050565b5f613c938383613c6c565b9150826002028217905092915050565b613cac82613035565b67ffffffffffffffff811115613cc557613cc46132e3565b5b613ccf8254613724565b613cda828285613c1a565b5f60209050601f831160018114613d0b575f8415613cf9578287015190505b613d038582613c88565b865550613d6a565b601f198416613d1986613b0c565b5f5b82811015613d4057848901518255600182019150602085019450602081019050613d1b565b86831015613d5d5784890151613d59601f891682613c6c565b8355505b6001600288020188555050505b505050505050565b7f55706461746573206172652066726f7a656e00000000000000000000000000005f82015250565b5f613da660128361303f565b9150613db182613d72565b602082019050919050565b5f6020820190508181035f830152613dd381613d9a565b9050919050565b7f546f6b656e20646f6573206e6f742065786973740000000000000000000000005f82015250565b5f613e0e60148361303f565b9150613e1982613dda565b602082019050919050565b5f6020820190508181035f830152613e3b81613e02565b9050919050565b7f55524c206e6f742073657420666f7220746f6b656e00000000000000000000005f82015250565b5f613e7660158361303f565b9150613e8182613e42565b602082019050919050565b5f6020820190508181035f830152613ea381613e6a565b9050919050565b5f81905092915050565b7f7b226e616d65223a20224d6f6e61644d6173636f7420000000000000000000005f82015250565b5f613ee8601683613eaa565b9150613ef382613eb4565b601682019050919050565b5f613f0882613035565b613f128185613eaa565b9350613f2281856020860161304f565b80840191505092915050565b7f222c20226465736372697074696f6e223a20224d6f6e61644d6173636f7473205f8201527f61726520756e6971756520706572736f6e616c697a6564206d6173636f74732060208201527f67656e657261746564207573696e67204661726361737465722064617461206660408201527f6f72206561636820757365722e222c2022696d616765223a2022000000000000606082015250565b5f613fd4607a83613eaa565b9150613fdf82613f2e565b607a82019050919050565b7f222c202261747472696275746573223a205b7b2274726169745f74797065223a5f8201527f202253706563696573222c202276616c7565223a20224d6f6e61644d6173636f60208201527f74227d5d7d000000000000000000000000000000000000000000000000000000604082015250565b5f61406a604583613eaa565b915061407582613fea565b604582019050919050565b5f61408a82613edc565b91506140968285613efe565b91506140a182613fc8565b91506140ad8284613efe565b91506140b88261405e565b91508190509392505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000005f82015250565b5f6140f8601d83613eaa565b9150614103826140c4565b601d82019050919050565b5f614118826140ec565b91506141248284613efe565b915081905092915050565b5f8160601b9050919050565b5f6141458261412f565b9050919050565b5f6141568261413b565b9050919050565b61416e61416982613142565b61414c565b82525050565b7f57504c54000000000000000000000000000000000000000000000000000000005f82015250565b5f6141a8600483613eaa565b91506141b382614174565b600482019050919050565b5f819050919050565b6141d86141d3826130c5565b6141be565b82525050565b5f6141e9828661415d565b6014820191506141f88261419c565b915061420482856141c7565b6020820191506142148284613efe565b9150819050949350505050565b5f81519050919050565b5f82825260208201905092915050565b5f61424582614221565b61424f818561422b565b935061425f81856020860161304f565b6142688161305d565b840191505092915050565b5f6080820190506142865f830187613153565b6142936020830186613153565b6142a06040830185613263565b81810360608301526142b2818461423b565b905095945050505050565b5f815190506142cb81612fad565b92915050565b5f602082840312156142e6576142e5612f7a565b5b5f6142f3848285016142bd565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614333826130c5565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614365576143646142fc565b5b600182019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6143a7826130c5565b91506143b2836130c5565b9250826143c2576143c1614370565b5b828204905092915050565b5f6143d7826130c5565b91506143e2836130c5565b92508282039050818111156143fa576143f96142fc565b5b92915050565b5f61440a826130c5565b9150614415836130c5565b92508261442557614424614370565b5b828206905092915050565b5f61443a826130c5565b9150614445836130c5565b925082820190508082111561445d5761445c6142fc565b5b92915050565b5f61446d826130c5565b9150614478836130c5565b9250828202614486816130c5565b9150828204841483151761449d5761449c6142fc565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f819050919050565b614510816144fe565b82525050565b5f6020820190506145295f830184614507565b92915050565b5f60ff82169050919050565b6145448161452f565b82525050565b5f60808201905061455d5f830187614507565b61456a602083018661453b565b6145776040830185614507565b6145846060830184614507565b9594505050505056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122006acf36b1e4c2d87474a555bd7329253049a1f6cffcc07a326b894e304abd56b64736f6c634300081e0033
Deployed Bytecode Sourcemap
157667:5088:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133567:224;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116953:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118021:158;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;117869:115;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;158782:161;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;161327:126;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;134145:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;157735:30;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118591:588;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;162575:177;;;;;;;;;;;;;:::i;:::-;;133838:260;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119216:134;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;157802:25;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;157834:81;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;134296:231;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156577:86;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116788:120;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;157956:24;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;116538:213;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3394:103;;;;;;;;;;;;;:::i;:::-;;158951:790;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2719:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;117089:95;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;118216:146;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;119387:236;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;158272:166;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;157924:25;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;159881:833;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;158446:162;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;118399:155;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3652:220;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;158616:158;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;162380:187;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;157772:23;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;133567:224;133669:4;133708:35;133693:50;;;:11;:50;;;;:90;;;;133747:36;133771:11;133747:23;:36::i;:::-;133693:90;133686:97;;133567:224;;;:::o;116953:91::-;116998:13;117031:5;117024:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;116953:91;:::o;118021:158::-;118088:7;118108:22;118122:7;118108:13;:22::i;:::-;;118150:21;118163:7;118150:12;:21::i;:::-;118143:28;;118021:158;;;:::o;117869:115::-;117941:35;117950:2;117954:7;117963:12;:10;:12::i;:::-;117941:8;:35::i;:::-;117869:115;;:::o;158782:161::-;2605:13;:11;:13::i;:::-;158849:7:::1;158845:91;;;158873:8;:6;:8::i;:::-;158845:91;;;158914:10;:8;:10::i;:::-;158845:91;158782:161:::0;:::o;161327:126::-;2605:13;:11;:13::i;:::-;161429:16:::1;161411:15;;:34;;;;;;;;;;;;;;;;;;161327:126:::0;:::o;134145:104::-;134197:7;134224:10;:17;;;;134217:24;;134145:104;:::o;157735:30::-;;;;;;;;;;;;;:::o;118591:588::-;118700:1;118686:16;;:2;:16;;;118682:89;;118756:1;118726:33;;;;;;;;;;;:::i;:::-;;;;;;;;118682:89;118992:21;119016:34;119024:2;119028:7;119037:12;:10;:12::i;:::-;119016:7;:34::i;:::-;118992:58;;119082:4;119065:21;;:13;:21;;;119061:111;;119131:4;119137:7;119146:13;119110:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;119061:111;118671:508;118591:588;;;:::o;162575:177::-;2605:13;:11;:13::i;:::-;162631:12:::1;162649:10;:15;;162672:21;162649:49;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;162630:68;;;162717:7;162709:35;;;;;;;;;;;;:::i;:::-;;;;;;;;;162619:133;162575:177::o:0;133838:260::-;133926:7;133959:16;133969:5;133959:9;:16::i;:::-;133950:5;:25;133946:101;;134022:5;134029;133999:36;;;;;;;;;;;;:::i;:::-;;;;;;;;133946:101;134064:12;:19;134077:5;134064:19;;;;;;;;;;;;;;;:26;134084:5;134064:26;;;;;;;;;;;;134057:33;;133838:260;;;;:::o;119216:134::-;119303:39;119320:4;119326:2;119330:7;119303:39;;;;;;;;;;;;:16;:39::i;:::-;119216:134;;;:::o;157802:25::-;;;;:::o;157834:81::-;157873:42;157834:81;:::o;134296:231::-;134362:7;134395:13;:11;:13::i;:::-;134386:5;:22;134382:103;;134463:1;134467:5;134432:41;;;;;;;;;;;;:::i;:::-;;;;;;;;134382:103;134502:10;134513:5;134502:17;;;;;;;;:::i;:::-;;;;;;;;;;134495:24;;134296:231;;;:::o;156577:86::-;156624:4;156648:7;;;;;;;;;;;156641:14;;156577:86;:::o;116788:120::-;116851:7;116878:22;116892:7;116878:13;:22::i;:::-;116871:29;;116788:120;;;:::o;157956:24::-;;;;:::o;116538:213::-;116601:7;116642:1;116625:19;;:5;:19;;;116621:89;;116695:1;116668:30;;;;;;;;;;;:::i;:::-;;;;;;;;116621:89;116727:9;:16;116737:5;116727:16;;;;;;;;;;;;;;;;116720:23;;116538:213;;;:::o;3394:103::-;2605:13;:11;:13::i;:::-;3459:30:::1;3486:1;3459:18;:30::i;:::-;3394:103::o:0;158951:790::-;159082:1;159068:3;159062:17;:21;159054:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;159153:1;159126:29;;:15;;;;;;;;;;;:29;;;:94;;;;159159:61;159183:10;159195:8;159205:3;159210:9;159159:23;:61::i;:::-;159126:94;159118:124;;;;;;;;;;;;:::i;:::-;;;;;;;;;159262:21;159274:8;159262:11;:21::i;:::-;159261:22;159253:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;159328:8;:6;:8::i;:::-;159327:9;159319:39;;;;;;;;;;;;:::i;:::-;;;;;;;;;159390:9;;159377;:22;;159369:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;159526:1;159496:32;;159504:9;;;;;;;;;;;159496:32;;;;:84;;;;;159570:10;;159532:9;;;;;;;;;;;:19;;;159560:4;159532:34;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:48;;159496:84;159492:161;;;159597:9;;;;;;;;;;;:18;;;157873:42;159630:10;;159597:44;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;159492:161;159665:31;159675:10;159687:8;159665:9;:31::i;:::-;159730:3;159707:10;:20;159718:8;159707:20;;;;;;;;;;;:26;;;;;;:::i;:::-;;158951:790;;;:::o;2719:87::-;2765:7;2792:6;;;;;;;;;;;2785:13;;2719:87;:::o;117089:95::-;117136:13;117169:7;117162:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;117089:95;:::o;118216:146::-;118302:52;118321:12;:10;:12::i;:::-;118335:8;118345;118302:18;:52::i;:::-;118216:146;;:::o;119387:236::-;119501:31;119514:4;119520:2;119524:7;119501:12;:31::i;:::-;119543:72;119577:12;:10;:12::i;:::-;119591:4;119597:2;119601:7;119610:4;119543:33;:72::i;:::-;119387:236;;;;:::o;158272:166::-;2605:13;:11;:13::i;:::-;158353::::1;;;;;;;;;;;158352:14;158344:45;;;;;;;;;;;;:::i;:::-;;;;;;;;;158419:10;158400:9;;:30;;;;;;;;;;;;;;;;;;158272:166:::0;:::o;157924:25::-;;;;;;;;;;;;;:::o;159881:833::-;159946:13;159980:20;159992:7;159980:11;:20::i;:::-;159972:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;160038:17;160058:10;:19;160069:7;160058:19;;;;;;;;;;;160038:39;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;160116:1;160102:3;160096:17;:21;160088:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;160156:18;160177:373;160275:17;160284:7;160275:8;:17::i;:::-;160447:3;160204:343;;;;;;;;;:::i;:::-;;;;;;;;;;;;;160177:13;:373::i;:::-;160156:394;;160676:4;160591:104;;;;;;;;:::i;:::-;;;;;;;;;;;;;160563:143;;;;159881:833;;;:::o;158446:162::-;2605:13;:11;:13::i;:::-;158529::::1;;;;;;;;;;;158528:14;158520:45;;;;;;;;;;;;:::i;:::-;;;;;;;;;158589:11;158576:10;:24;;;;158446:162:::0;:::o;118399:155::-;118487:4;118511:18;:25;118530:5;118511:25;;;;;;;;;;;;;;;:35;118537:8;118511:35;;;;;;;;;;;;;;;;;;;;;;;;;118504:42;;118399:155;;;;:::o;3652:220::-;2605:13;:11;:13::i;:::-;3757:1:::1;3737:22;;:8;:22;;::::0;3733:93:::1;;3811:1;3783:31;;;;;;;;;;;:::i;:::-;;;;;;;;3733:93;3836:28;3855:8;3836:18;:28::i;:::-;3652:220:::0;:::o;158616:158::-;2605:13;:11;:13::i;:::-;158697::::1;;;;;;;;;;;158696:14;158688:45;;;;;;;;;;;;:::i;:::-;;;;;;;;;158756:10;158744:9;:22;;;;158616:158:::0;:::o;162380:187::-;2605:13;:11;:13::i;:::-;162478:20:::1;162490:7;162478:11;:20::i;:::-;162470:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;162556:3;162534:10;:19;162545:7;162534:19;;;;;;;;;;;:25;;;;;;:::i;:::-;;162380:187:::0;;:::o;157772:23::-;;;;;;;;;;;;;:::o;116196:305::-;116298:4;116350:25;116335:40;;;:11;:40;;;;:105;;;;116407:33;116392:48;;;:11;:48;;;;116335:105;:158;;;;116457:36;116481:11;116457:23;:36::i;:::-;116335:158;116315:178;;116196:305;;;:::o;130905:247::-;130968:7;130988:13;131004:17;131013:7;131004:8;:17::i;:::-;130988:33;;131053:1;131036:19;;:5;:19;;;131032:90;;131102:7;131079:31;;;;;;;;;;;:::i;:::-;;;;;;;;131032:90;131139:5;131132:12;;;130905:247;;;:::o;120386:129::-;120456:7;120483:15;:24;120499:7;120483:24;;;;;;;;;;;;;;;;;;;;;120476:31;;120386:129;;;:::o;728:98::-;781:7;808:10;801:17;;728:98;:::o;129137:122::-;129218:33;129227:2;129231:7;129240:4;129246;129218:8;:33::i;:::-;129137:122;;;:::o;2884:166::-;2955:12;:10;:12::i;:::-;2944:23;;:7;:5;:7::i;:::-;:23;;;2940:103;;3018:12;:10;:12::i;:::-;2991:40;;;;;;;;;;;:::i;:::-;;;;;;;;2940:103;2884:166::o;157219:118::-;156182:19;:17;:19::i;:::-;157289:4:::1;157279:7;;:14;;;;;;;;;;;;;;;;;;157309:20;157316:12;:10;:12::i;:::-;157309:20;;;;;;:::i;:::-;;;;;;;;157219:118::o:0;157478:120::-;156441:16;:14;:16::i;:::-;157547:5:::1;157537:7;;:15;;;;;;;;;;;;;;;;;;157568:22;157577:12;:10;:12::i;:::-;157568:22;;;;;;:::i;:::-;;;;;;;;157478:120::o:0;134563:640::-;134658:7;134678:21;134702:32;134716:2;134720:7;134729:4;134702:13;:32::i;:::-;134678:56;;134776:1;134751:27;;:13;:27;;;134747:214;;134795:40;134827:7;134795:31;:40::i;:::-;134747:214;;;134874:2;134857:19;;:13;:19;;;134853:108;;134893:56;134926:13;134941:7;134893:32;:56::i;:::-;134853:108;134747:214;134989:1;134975:16;;:2;:16;;;134971:192;;135008:45;135045:7;135008:36;:45::i;:::-;134971:192;;;135092:2;135075:19;;:13;:19;;;135071:92;;135111:40;135139:2;135143:7;135111:27;:40::i;:::-;135071:92;134971:192;135182:13;135175:20;;;134563:640;;;;;:::o;4032:191::-;4106:16;4125:6;;;;;;;;;;;4106:25;;4151:8;4142:6;;:17;;;;;;;;;;;;;;;;;;4206:8;4175:40;;4196:8;4175:40;;;;;;;;;;;;4095:128;4032:191;:::o;161905:467::-;162037:4;162054:19;162103:6;162119:7;162128:3;162086:46;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;162076:57;;;;;;162054:79;;162144:28;162175:52;162215:11;162175:39;:52::i;:::-;162144:83;;162238:23;162264:46;162278:20;162300:9;162264:13;:46::i;:::-;162238:72;;162349:15;;;;;;;;;;;162330:34;;:15;:34;;;162323:41;;;;;161905:467;;;;;;:::o;159749:124::-;159810:4;159863:1;159834:31;;:17;159843:7;159834:8;:17::i;:::-;:31;;;;159827:38;;159749:124;;;:::o;125205:102::-;125273:26;125283:2;125287:7;125273:26;;;;;;;;;;;;:9;:26::i;:::-;125205:102;;:::o;130344:318::-;130472:1;130452:22;;:8;:22;;;130448:93;;130520:8;130498:31;;;;;;;;;;;:::i;:::-;;;;;;;;130448:93;130589:8;130551:18;:25;130570:5;130551:25;;;;;;;;;;;;;;;:35;130577:8;130551:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;130635:8;130613:41;;130628:5;130613:41;;;130645:8;130613:41;;;;;;:::i;:::-;;;;;;;;130344:318;;;:::o;19758:950::-;19962:1;19945:2;:14;;;:18;19941:760;;;20000:2;19984:36;;;20021:8;20031:4;20037:7;20046:4;19984:67;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;19980:710;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20364:1;20347:6;:13;:18;20343:332;;20489:2;20453:39;;;;;;;;;;;:::i;:::-;;;;;;;;20343:332;20625:6;20619:13;20612:4;20604:6;20600:17;20593:40;19980:710;20109:41;;;20099:51;;;:6;:51;;;;20095:185;;20257:2;20221:39;;;;;;;;;;;:::i;:::-;;;;;;;;20095:185;20052:243;19941:760;19758:950;;;;;:::o;160722:597::-;160778:13;160882:1;160873:5;:10;160869:53;;160900:10;;;;;;;;;;;;;;;;;;;;;160869:53;160932:12;160947:5;160932:20;;160963:14;160988:78;161003:1;160995:4;:9;160988:78;;161021:8;;;;;:::i;:::-;;;;161052:2;161044:10;;;;;:::i;:::-;;;160988:78;;;161076:19;161108:6;161098:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;161076:39;;161126:154;161142:1;161133:5;:10;161126:154;;161170:1;161160:11;;;;;:::i;:::-;;;161237:2;161229:5;:10;;;;:::i;:::-;161216:2;:24;;;;:::i;:::-;161203:39;;161186:6;161193;161186:14;;;;;;;;:::i;:::-;;;;;:56;;;;;;;;;;;161266:2;161257:11;;;;;:::i;:::-;;;161126:154;;;161304:6;161290:21;;;;;160722:597;;;;:::o;163106:1607::-;163164:13;163190:11;163204:4;:11;163190:25;;163237:1;163230:3;:8;163226:23;;163240:9;;;;;;;;;;;;;;;;;163226:23;163301:18;163339:1;163334;163328:3;:7;;;;:::i;:::-;163327:13;;;;:::i;:::-;163322:1;:19;;;;:::i;:::-;163301:40;;163399:19;163444:2;163431:10;:15;;;;:::i;:::-;163421:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;163399:48;;163460:18;163481:5;;;;;;;;;;;;;;;;;163460:26;;163550:1;163543:5;163539:13;163595:2;163587:6;163583:15;163646:1;163614:777;163669:3;163666:1;163663:10;163614:777;;;163724:1;163721;163717:9;163712:14;;163782:8;163777:1;163771:4;163767:12;163761:19;163757:34;163862:4;163854:5;163850:2;163846:14;163842:25;163832:8;163828:40;163822:47;163901:3;163898:1;163894:11;163887:18;;163992:4;163983;163975:5;163971:2;163967:14;163963:25;163953:8;163949:40;163943:47;163939:58;163934:3;163930:68;163923:75;;164030:3;164027:1;164023:11;164016:18;;164120:4;164111;164103:5;164100:1;164096:13;164092:24;164082:8;164078:39;164072:46;164068:57;164063:3;164059:67;164052:74;;164158:3;164155:1;164151:11;164144:18;;164240:4;164231;164224:5;164220:16;164210:8;164206:31;164200:38;164196:49;164191:3;164187:59;164180:66;;164280:3;164275;164271:13;164264:20;;164322:3;164311:9;164304:22;164374:1;164363:9;164359:17;164346:30;;163693:698;;163614:777;;;163618:44;164423:1;164418:3;164414:11;164444:1;164439:84;;;;164542:1;164537:82;;;;164407:212;;164439:84;164500:6;164495:3;164491:16;164487:1;164476:9;164472:17;164465:43;164439:84;;164537:82;164598:4;164593:3;164589:14;164585:1;164574:9;164570:17;164563:41;164407:212;;164650:10;164642:6;164635:26;163508:1164;;164698:6;164684:21;;;;;;163106:1607;;;;:::o;114829:148::-;114905:4;114944:25;114929:40;;;:11;:40;;;;114922:47;;114829:148;;;:::o;120148:117::-;120214:7;120241;:16;120249:7;120241:16;;;;;;;;;;;;;;;;;;;;;120234:23;;120148:117;;;:::o;129447:678::-;129609:9;:31;;;;129638:1;129622:18;;:4;:18;;;;129609:31;129605:471;;;129657:13;129673:22;129687:7;129673:13;:22::i;:::-;129657:38;;129842:1;129826:18;;:4;:18;;;;:35;;;;;129857:4;129848:13;;:5;:13;;;;129826:35;:69;;;;;129866:29;129883:5;129890:4;129866:16;:29::i;:::-;129865:30;129826:69;129822:144;;;129945:4;129923:27;;;;;;;;;;;:::i;:::-;;;;;;;;129822:144;129986:9;129982:83;;;130041:7;130037:2;130021:28;;130030:5;130021:28;;;;;;;;;;;;129982:83;129642:434;129605:471;130115:2;130088:15;:24;130104:7;130088:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;129447:678;;;;:::o;156736:132::-;156802:8;:6;:8::i;:::-;156798:63;;;156834:15;;;;;;;;;;;;;;156798:63;156736:132::o;156945:130::-;157009:8;:6;:8::i;:::-;157004:64;;157041:15;;;;;;;;;;;;;;157004:64;156945:130::o;123347:824::-;123433:7;123453:12;123468:17;123477:7;123468:8;:17::i;:::-;123453:32;;123564:1;123548:18;;:4;:18;;;123544:88;;123583:37;123600:4;123606;123612:7;123583:16;:37::i;:::-;123544:88;123695:1;123679:18;;:4;:18;;;123675:263;;123797:48;123814:1;123818:7;123835:1;123839:5;123797:8;:48::i;:::-;123910:1;123891:9;:15;123901:4;123891:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;123675:263;123968:1;123954:16;;:2;:16;;;123950:111;;124033:1;124016:9;:13;124026:2;124016:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;123950:111;124092:2;124073:7;:16;124081:7;124073:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;124131:7;124127:2;124112:27;;124121:4;124112:27;;;;;;;;;;;;124159:4;124152:11;;;123347:824;;;;;:::o;135923:164::-;136027:10;:17;;;;136000:15;:24;136016:7;136000:24;;;;;;;;;;;:44;;;;136055:10;136071:7;136055:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135923:164;:::o;136714:1075::-;136980:22;137005:15;137015:4;137005:9;:15::i;:::-;136980:40;;137031:18;137052:17;:26;137070:7;137052:26;;;;;;;;;;;;137031:47;;137091:61;137155:12;:18;137168:4;137155:18;;;;;;;;;;;;;;;137091:82;;137294:14;137280:10;:28;137276:330;;137325:19;137347;:35;137367:14;137347:35;;;;;;;;;;;;137325:57;;137433:11;137399:19;:31;137419:10;137399:31;;;;;;;;;;;:45;;;;137550:10;137517:17;:30;137535:11;137517:30;;;;;;;;;;;:43;;;;137310:296;137276:330;137702:17;:26;137720:7;137702:26;;;;;;;;;;;137695:33;;;137746:19;:35;137766:14;137746:35;;;;;;;;;;;137739:42;;;136795:994;;;136714:1075;;:::o;138084:1079::-;138337:22;138382:1;138362:10;:17;;;;:21;;;;:::i;:::-;138337:46;;138394:18;138415:15;:24;138431:7;138415:24;;;;;;;;;;;;138394:45;;138766:19;138788:10;138799:14;138788:26;;;;;;;;:::i;:::-;;;;;;;;;;138766:48;;138852:11;138827:10;138838;138827:22;;;;;;;;:::i;:::-;;;;;;;;;:36;;;;138963:10;138932:15;:28;138948:11;138932:28;;;;;;;;;;;:41;;;;139104:15;:24;139120:7;139104:24;;;;;;;;;;;139097:31;;;139139:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;138155:1008;;;138084:1079;:::o;135504:218::-;135589:14;135622:1;135606:13;135616:2;135606:9;:13::i;:::-;:17;;;;:::i;:::-;135589:34;;135661:7;135634:12;:16;135647:2;135634:16;;;;;;;;;;;;;;;:24;135651:6;135634:24;;;;;;;;;;;:34;;;;135708:6;135679:17;:26;135697:7;135679:26;;;;;;;;;;;:35;;;;135578:144;135504:218;;:::o;151732:439::-;151808:14;151888:34;151882:4;151875:48;151991:11;151985:4;151978:25;152084:4;152078;152068:21;152058:31;;151732:439;;;:::o;146259:259::-;146337:7;146358:17;146377:18;146397:16;146417:27;146428:4;146434:9;146417:10;:27::i;:::-;146357:87;;;;;;146455:28;146467:5;146474:8;146455:11;:28::i;:::-;146501:9;146494:16;;;;;146259:259;;;;:::o;125534:210::-;125629:18;125635:2;125639:7;125629:5;:18::i;:::-;125658:78;125692:12;:10;:12::i;:::-;125714:1;125718:2;125722:7;125731:4;125658:33;:78::i;:::-;125534:210;;;:::o;121554:376::-;121667:38;121681:5;121688:7;121697;121667:13;:38::i;:::-;121662:261;;121743:1;121726:19;;:5;:19;;;121722:190;;121796:7;121773:31;;;;;;;;;;;:::i;:::-;;;;;;;;121722:190;121879:7;121888;121852:44;;;;;;;;;;;;:::i;:::-;;;;;;;;121662:261;121554:376;;;:::o;144639:797::-;144745:17;144764:16;144782:14;144833:2;144813:9;:16;:22;144809:620;;144852:9;144876;144900:7;145125:4;145114:9;145110:20;145104:27;145099:32;;145175:4;145164:9;145160:20;145154:27;145149:32;;145233:4;145222:9;145218:20;145212:27;145209:1;145204:36;145199:41;;145276:25;145287:4;145293:1;145296;145299;145276:10;:25::i;:::-;145269:32;;;;;;;;;;;144809:620;145350:1;145354:35;145399:9;:16;145391:25;;145334:83;;;;;;144639:797;;;;;;:::o;149903:542::-;149999:20;149990:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;149986:452;150036:7;149986:452;150097:29;150088:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;150084:354;;150150:23;;;;;;;;;;;;;;150084:354;150204:35;150195:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;150191:247;;150299:8;150291:17;;150263:46;;;;;;;;;;;:::i;:::-;;;;;;;;150191:247;150340:30;150331:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;150327:111;;150417:8;150394:32;;;;;;;;;;;:::i;:::-;;;;;;;;150327:111;149903:542;;;:::o;124507:335::-;124589:1;124575:16;;:2;:16;;;124571:89;;124645:1;124615:33;;;;;;;;;;;:::i;:::-;;;;;;;;124571:89;124670:21;124694:32;124702:2;124706:7;124723:1;124694:7;:32::i;:::-;124670:56;;124766:1;124741:27;;:13;:27;;;124737:98;;124820:1;124792:31;;;;;;;;;;;:::i;:::-;;;;;;;;124737:98;124560:282;124507:335;;:::o;120835:276::-;120938:4;120994:1;120975:21;;:7;:21;;;;:128;;;;;121023:7;121014:16;;:5;:16;;;:52;;;;121034:32;121051:5;121058:7;121034:16;:32::i;:::-;121014:52;:88;;;;121095:7;121070:32;;:21;121083:7;121070:12;:21::i;:::-;:32;;;121014:88;120975:128;120955:148;;120835:276;;;;;:::o;147785:1577::-;147916:17;147935:16;147953:14;148880:66;148875:1;148867:10;;:79;148863:166;;;148979:1;148983:30;149015:1;148963:54;;;;;;;;148863:166;149126:14;149143:24;149153:4;149159:1;149162;149165;149143:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;149126:41;;149200:1;149182:20;;:6;:20;;;149178:115;;149235:1;149239:29;149278:1;149270:10;;149219:62;;;;;;;;;149178:115;149313:6;149321:20;149351:1;149343:10;;149305:49;;;;;;;147785:1577;;;;;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:139::-;1887:6;1882:3;1877;1871:23;1928:1;1919:6;1914:3;1910:16;1903:27;1798:139;;;:::o;1943:102::-;1984:6;2035:2;2031:7;2026:2;2019:5;2015:14;2011:28;2001:38;;1943:102;;;:::o;2051:377::-;2139:3;2167:39;2200:5;2167:39;:::i;:::-;2222:71;2286:6;2281:3;2222:71;:::i;:::-;2215:78;;2302:65;2360:6;2355:3;2348:4;2341:5;2337:16;2302:65;:::i;:::-;2392:29;2414:6;2392:29;:::i;:::-;2387:3;2383:39;2376:46;;2143:285;2051:377;;;;:::o;2434:313::-;2547:4;2585:2;2574:9;2570:18;2562:26;;2634:9;2628:4;2624:20;2620:1;2609:9;2605:17;2598:47;2662:78;2735:4;2726:6;2662:78;:::i;:::-;2654:86;;2434:313;;;;:::o;2753:77::-;2790:7;2819:5;2808:16;;2753:77;;;:::o;2836:122::-;2909:24;2927:5;2909:24;:::i;:::-;2902:5;2899:35;2889:63;;2948:1;2945;2938:12;2889:63;2836:122;:::o;2964:139::-;3010:5;3048:6;3035:20;3026:29;;3064:33;3091:5;3064:33;:::i;:::-;2964:139;;;;:::o;3109:329::-;3168:6;3217:2;3205:9;3196:7;3192:23;3188:32;3185:119;;;3223:79;;:::i;:::-;3185:119;3343:1;3368:53;3413:7;3404:6;3393:9;3389:22;3368:53;:::i;:::-;3358:63;;3314:117;3109:329;;;;:::o;3444:126::-;3481:7;3521:42;3514:5;3510:54;3499:65;;3444:126;;;:::o;3576:96::-;3613:7;3642:24;3660:5;3642:24;:::i;:::-;3631:35;;3576:96;;;:::o;3678:118::-;3765:24;3783:5;3765:24;:::i;:::-;3760:3;3753:37;3678:118;;:::o;3802:222::-;3895:4;3933:2;3922:9;3918:18;3910:26;;3946:71;4014:1;4003:9;3999:17;3990:6;3946:71;:::i;:::-;3802:222;;;;:::o;4030:122::-;4103:24;4121:5;4103:24;:::i;:::-;4096:5;4093:35;4083:63;;4142:1;4139;4132:12;4083:63;4030:122;:::o;4158:139::-;4204:5;4242:6;4229:20;4220:29;;4258:33;4285:5;4258:33;:::i;:::-;4158:139;;;;:::o;4303:474::-;4371:6;4379;4428:2;4416:9;4407:7;4403:23;4399:32;4396:119;;;4434:79;;:::i;:::-;4396:119;4554:1;4579:53;4624:7;4615:6;4604:9;4600:22;4579:53;:::i;:::-;4569:63;;4525:117;4681:2;4707:53;4752:7;4743:6;4732:9;4728:22;4707:53;:::i;:::-;4697:63;;4652:118;4303:474;;;;;:::o;4783:116::-;4853:21;4868:5;4853:21;:::i;:::-;4846:5;4843:32;4833:60;;4889:1;4886;4879:12;4833:60;4783:116;:::o;4905:133::-;4948:5;4986:6;4973:20;4964:29;;5002:30;5026:5;5002:30;:::i;:::-;4905:133;;;;:::o;5044:323::-;5100:6;5149:2;5137:9;5128:7;5124:23;5120:32;5117:119;;;5155:79;;:::i;:::-;5117:119;5275:1;5300:50;5342:7;5333:6;5322:9;5318:22;5300:50;:::i;:::-;5290:60;;5246:114;5044:323;;;;:::o;5373:329::-;5432:6;5481:2;5469:9;5460:7;5456:23;5452:32;5449:119;;;5487:79;;:::i;:::-;5449:119;5607:1;5632:53;5677:7;5668:6;5657:9;5653:22;5632:53;:::i;:::-;5622:63;;5578:117;5373:329;;;;:::o;5708:118::-;5795:24;5813:5;5795:24;:::i;:::-;5790:3;5783:37;5708:118;;:::o;5832:222::-;5925:4;5963:2;5952:9;5948:18;5940:26;;5976:71;6044:1;6033:9;6029:17;6020:6;5976:71;:::i;:::-;5832:222;;;;:::o;6060:619::-;6137:6;6145;6153;6202:2;6190:9;6181:7;6177:23;6173:32;6170:119;;;6208:79;;:::i;:::-;6170:119;6328:1;6353:53;6398:7;6389:6;6378:9;6374:22;6353:53;:::i;:::-;6343:63;;6299:117;6455:2;6481:53;6526:7;6517:6;6506:9;6502:22;6481:53;:::i;:::-;6471:63;;6426:118;6583:2;6609:53;6654:7;6645:6;6634:9;6630:22;6609:53;:::i;:::-;6599:63;;6554:118;6060:619;;;;;:::o;6685:117::-;6794:1;6791;6784:12;6808:117;6917:1;6914;6907:12;6931:180;6979:77;6976:1;6969:88;7076:4;7073:1;7066:15;7100:4;7097:1;7090:15;7117:281;7200:27;7222:4;7200:27;:::i;:::-;7192:6;7188:40;7330:6;7318:10;7315:22;7294:18;7282:10;7279:34;7276:62;7273:88;;;7341:18;;:::i;:::-;7273:88;7381:10;7377:2;7370:22;7160:238;7117:281;;:::o;7404:129::-;7438:6;7465:20;;:::i;:::-;7455:30;;7494:33;7522:4;7514:6;7494:33;:::i;:::-;7404:129;;;:::o;7539:308::-;7601:4;7691:18;7683:6;7680:30;7677:56;;;7713:18;;:::i;:::-;7677:56;7751:29;7773:6;7751:29;:::i;:::-;7743:37;;7835:4;7829;7825:15;7817:23;;7539:308;;;:::o;7853:148::-;7951:6;7946:3;7941;7928:30;7992:1;7983:6;7978:3;7974:16;7967:27;7853:148;;;:::o;8007:425::-;8085:5;8110:66;8126:49;8168:6;8126:49;:::i;:::-;8110:66;:::i;:::-;8101:75;;8199:6;8192:5;8185:21;8237:4;8230:5;8226:16;8275:3;8266:6;8261:3;8257:16;8254:25;8251:112;;;8282:79;;:::i;:::-;8251:112;8372:54;8419:6;8414:3;8409;8372:54;:::i;:::-;8091:341;8007:425;;;;;:::o;8452:340::-;8508:5;8557:3;8550:4;8542:6;8538:17;8534:27;8524:122;;8565:79;;:::i;:::-;8524:122;8682:6;8669:20;8707:79;8782:3;8774:6;8767:4;8759:6;8755:17;8707:79;:::i;:::-;8698:88;;8514:278;8452:340;;;;:::o;8798:307::-;8859:4;8949:18;8941:6;8938:30;8935:56;;;8971:18;;:::i;:::-;8935:56;9009:29;9031:6;9009:29;:::i;:::-;9001:37;;9093:4;9087;9083:15;9075:23;;8798:307;;;:::o;9111:423::-;9188:5;9213:65;9229:48;9270:6;9229:48;:::i;:::-;9213:65;:::i;:::-;9204:74;;9301:6;9294:5;9287:21;9339:4;9332:5;9328:16;9377:3;9368:6;9363:3;9359:16;9356:25;9353:112;;;9384:79;;:::i;:::-;9353:112;9474:54;9521:6;9516:3;9511;9474:54;:::i;:::-;9194:340;9111:423;;;;;:::o;9553:338::-;9608:5;9657:3;9650:4;9642:6;9638:17;9634:27;9624:122;;9665:79;;:::i;:::-;9624:122;9782:6;9769:20;9807:78;9881:3;9873:6;9866:4;9858:6;9854:17;9807:78;:::i;:::-;9798:87;;9614:277;9553:338;;;;:::o;9897:977::-;9993:6;10001;10009;10058:2;10046:9;10037:7;10033:23;10029:32;10026:119;;;10064:79;;:::i;:::-;10026:119;10184:1;10209:53;10254:7;10245:6;10234:9;10230:22;10209:53;:::i;:::-;10199:63;;10155:117;10339:2;10328:9;10324:18;10311:32;10370:18;10362:6;10359:30;10356:117;;;10392:79;;:::i;:::-;10356:117;10497:63;10552:7;10543:6;10532:9;10528:22;10497:63;:::i;:::-;10487:73;;10282:288;10637:2;10626:9;10622:18;10609:32;10668:18;10660:6;10657:30;10654:117;;;10690:79;;:::i;:::-;10654:117;10795:62;10849:7;10840:6;10829:9;10825:22;10795:62;:::i;:::-;10785:72;;10580:287;9897:977;;;;;:::o;10880:468::-;10945:6;10953;11002:2;10990:9;10981:7;10977:23;10973:32;10970:119;;;11008:79;;:::i;:::-;10970:119;11128:1;11153:53;11198:7;11189:6;11178:9;11174:22;11153:53;:::i;:::-;11143:63;;11099:117;11255:2;11281:50;11323:7;11314:6;11303:9;11299:22;11281:50;:::i;:::-;11271:60;;11226:115;10880:468;;;;;:::o;11354:943::-;11449:6;11457;11465;11473;11522:3;11510:9;11501:7;11497:23;11493:33;11490:120;;;11529:79;;:::i;:::-;11490:120;11649:1;11674:53;11719:7;11710:6;11699:9;11695:22;11674:53;:::i;:::-;11664:63;;11620:117;11776:2;11802:53;11847:7;11838:6;11827:9;11823:22;11802:53;:::i;:::-;11792:63;;11747:118;11904:2;11930:53;11975:7;11966:6;11955:9;11951:22;11930:53;:::i;:::-;11920:63;;11875:118;12060:2;12049:9;12045:18;12032:32;12091:18;12083:6;12080:30;12077:117;;;12113:79;;:::i;:::-;12077:117;12218:62;12272:7;12263:6;12252:9;12248:22;12218:62;:::i;:::-;12208:72;;12003:287;11354:943;;;;;;;:::o;12303:474::-;12371:6;12379;12428:2;12416:9;12407:7;12403:23;12399:32;12396:119;;;12434:79;;:::i;:::-;12396:119;12554:1;12579:53;12624:7;12615:6;12604:9;12600:22;12579:53;:::i;:::-;12569:63;;12525:117;12681:2;12707:53;12752:7;12743:6;12732:9;12728:22;12707:53;:::i;:::-;12697:63;;12652:118;12303:474;;;;;:::o;12783:654::-;12861:6;12869;12918:2;12906:9;12897:7;12893:23;12889:32;12886:119;;;12924:79;;:::i;:::-;12886:119;13044:1;13069:53;13114:7;13105:6;13094:9;13090:22;13069:53;:::i;:::-;13059:63;;13015:117;13199:2;13188:9;13184:18;13171:32;13230:18;13222:6;13219:30;13216:117;;;13252:79;;:::i;:::-;13216:117;13357:63;13412:7;13403:6;13392:9;13388:22;13357:63;:::i;:::-;13347:73;;13142:288;12783:654;;;;;:::o;13443:60::-;13471:3;13492:5;13485:12;;13443:60;;;:::o;13509:142::-;13559:9;13592:53;13610:34;13619:24;13637:5;13619:24;:::i;:::-;13610:34;:::i;:::-;13592:53;:::i;:::-;13579:66;;13509:142;;;:::o;13657:126::-;13707:9;13740:37;13771:5;13740:37;:::i;:::-;13727:50;;13657:126;;;:::o;13789:141::-;13854:9;13887:37;13918:5;13887:37;:::i;:::-;13874:50;;13789:141;;;:::o;13936:161::-;14038:52;14084:5;14038:52;:::i;:::-;14033:3;14026:65;13936:161;;:::o;14103:252::-;14211:4;14249:2;14238:9;14234:18;14226:26;;14262:86;14345:1;14334:9;14330:17;14321:6;14262:86;:::i;:::-;14103:252;;;;:::o;14361:180::-;14409:77;14406:1;14399:88;14506:4;14503:1;14496:15;14530:4;14527:1;14520:15;14547:320;14591:6;14628:1;14622:4;14618:12;14608:22;;14675:1;14669:4;14665:12;14696:18;14686:81;;14752:4;14744:6;14740:17;14730:27;;14686:81;14814:2;14806:6;14803:14;14783:18;14780:38;14777:84;;14833:18;;:::i;:::-;14777:84;14598:269;14547:320;;;:::o;14873:442::-;15022:4;15060:2;15049:9;15045:18;15037:26;;15073:71;15141:1;15130:9;15126:17;15117:6;15073:71;:::i;:::-;15154:72;15222:2;15211:9;15207:18;15198:6;15154:72;:::i;:::-;15236;15304:2;15293:9;15289:18;15280:6;15236:72;:::i;:::-;14873:442;;;;;;:::o;15321:147::-;15422:11;15459:3;15444:18;;15321:147;;;;:::o;15474:114::-;;:::o;15594:398::-;15753:3;15774:83;15855:1;15850:3;15774:83;:::i;:::-;15767:90;;15866:93;15955:3;15866:93;:::i;:::-;15984:1;15979:3;15975:11;15968:18;;15594:398;;;:::o;15998:379::-;16182:3;16204:147;16347:3;16204:147;:::i;:::-;16197:154;;16368:3;16361:10;;15998:379;;;:::o;16383:165::-;16523:17;16519:1;16511:6;16507:14;16500:41;16383:165;:::o;16554:366::-;16696:3;16717:67;16781:2;16776:3;16717:67;:::i;:::-;16710:74;;16793:93;16882:3;16793:93;:::i;:::-;16911:2;16906:3;16902:12;16895:19;;16554:366;;;:::o;16926:419::-;17092:4;17130:2;17119:9;17115:18;17107:26;;17179:9;17173:4;17169:20;17165:1;17154:9;17150:17;17143:47;17207:131;17333:4;17207:131;:::i;:::-;17199:139;;16926:419;;;:::o;17351:332::-;17472:4;17510:2;17499:9;17495:18;17487:26;;17523:71;17591:1;17580:9;17576:17;17567:6;17523:71;:::i;:::-;17604:72;17672:2;17661:9;17657:18;17648:6;17604:72;:::i;:::-;17351:332;;;;;:::o;17689:180::-;17737:77;17734:1;17727:88;17834:4;17831:1;17824:15;17858:4;17855:1;17848:15;17875:169;18015:21;18011:1;18003:6;17999:14;17992:45;17875:169;:::o;18050:366::-;18192:3;18213:67;18277:2;18272:3;18213:67;:::i;:::-;18206:74;;18289:93;18378:3;18289:93;:::i;:::-;18407:2;18402:3;18398:12;18391:19;;18050:366;;;:::o;18422:419::-;18588:4;18626:2;18615:9;18611:18;18603:26;;18675:9;18669:4;18665:20;18661:1;18650:9;18646:17;18639:47;18703:131;18829:4;18703:131;:::i;:::-;18695:139;;18422:419;;;:::o;18847:167::-;18987:19;18983:1;18975:6;18971:14;18964:43;18847:167;:::o;19020:366::-;19162:3;19183:67;19247:2;19242:3;19183:67;:::i;:::-;19176:74;;19259:93;19348:3;19259:93;:::i;:::-;19377:2;19372:3;19368:12;19361:19;;19020:366;;;:::o;19392:419::-;19558:4;19596:2;19585:9;19581:18;19573:26;;19645:9;19639:4;19635:20;19631:1;19620:9;19616:17;19609:47;19673:131;19799:4;19673:131;:::i;:::-;19665:139;;19392:419;;;:::o;19817:170::-;19957:22;19953:1;19945:6;19941:14;19934:46;19817:170;:::o;19993:366::-;20135:3;20156:67;20220:2;20215:3;20156:67;:::i;:::-;20149:74;;20232:93;20321:3;20232:93;:::i;:::-;20350:2;20345:3;20341:12;20334:19;;19993:366;;;:::o;20365:419::-;20531:4;20569:2;20558:9;20554:18;20546:26;;20618:9;20612:4;20608:20;20604:1;20593:9;20589:17;20582:47;20646:131;20772:4;20646:131;:::i;:::-;20638:139;;20365:419;;;:::o;20790:167::-;20930:19;20926:1;20918:6;20914:14;20907:43;20790:167;:::o;20963:366::-;21105:3;21126:67;21190:2;21185:3;21126:67;:::i;:::-;21119:74;;21202:93;21291:3;21202:93;:::i;:::-;21320:2;21315:3;21311:12;21304:19;;20963:366;;;:::o;21335:419::-;21501:4;21539:2;21528:9;21524:18;21516:26;;21588:9;21582:4;21578:20;21574:1;21563:9;21559:17;21552:47;21616:131;21742:4;21616:131;:::i;:::-;21608:139;;21335:419;;;:::o;21760:170::-;21900:22;21896:1;21888:6;21884:14;21877:46;21760:170;:::o;21936:366::-;22078:3;22099:67;22163:2;22158:3;22099:67;:::i;:::-;22092:74;;22175:93;22264:3;22175:93;:::i;:::-;22293:2;22288:3;22284:12;22277:19;;21936:366;;;:::o;22308:419::-;22474:4;22512:2;22501:9;22497:18;22489:26;;22561:9;22555:4;22551:20;22547:1;22536:9;22532:17;22525:47;22589:131;22715:4;22589:131;:::i;:::-;22581:139;;22308:419;;;:::o;22733:143::-;22790:5;22821:6;22815:13;22806:22;;22837:33;22864:5;22837:33;:::i;:::-;22733:143;;;;:::o;22882:351::-;22952:6;23001:2;22989:9;22980:7;22976:23;22972:32;22969:119;;;23007:79;;:::i;:::-;22969:119;23127:1;23152:64;23208:7;23199:6;23188:9;23184:22;23152:64;:::i;:::-;23142:74;;23098:128;22882:351;;;;:::o;23239:137::-;23293:5;23324:6;23318:13;23309:22;;23340:30;23364:5;23340:30;:::i;:::-;23239:137;;;;:::o;23382:345::-;23449:6;23498:2;23486:9;23477:7;23473:23;23469:32;23466:119;;;23504:79;;:::i;:::-;23466:119;23624:1;23649:61;23702:7;23693:6;23682:9;23678:22;23649:61;:::i;:::-;23639:71;;23595:125;23382:345;;;;:::o;23733:141::-;23782:4;23805:3;23797:11;;23828:3;23825:1;23818:14;23862:4;23859:1;23849:18;23841:26;;23733:141;;;:::o;23880:93::-;23917:6;23964:2;23959;23952:5;23948:14;23944:23;23934:33;;23880:93;;;:::o;23979:107::-;24023:8;24073:5;24067:4;24063:16;24042:37;;23979:107;;;;:::o;24092:393::-;24161:6;24211:1;24199:10;24195:18;24234:97;24264:66;24253:9;24234:97;:::i;:::-;24352:39;24382:8;24371:9;24352:39;:::i;:::-;24340:51;;24424:4;24420:9;24413:5;24409:21;24400:30;;24473:4;24463:8;24459:19;24452:5;24449:30;24439:40;;24168:317;;24092:393;;;;;:::o;24491:142::-;24541:9;24574:53;24592:34;24601:24;24619:5;24601:24;:::i;:::-;24592:34;:::i;:::-;24574:53;:::i;:::-;24561:66;;24491:142;;;:::o;24639:75::-;24682:3;24703:5;24696:12;;24639:75;;;:::o;24720:269::-;24830:39;24861:7;24830:39;:::i;:::-;24891:91;24940:41;24964:16;24940:41;:::i;:::-;24932:6;24925:4;24919:11;24891:91;:::i;:::-;24885:4;24878:105;24796:193;24720:269;;;:::o;24995:73::-;25040:3;25061:1;25054:8;;24995:73;:::o;25074:189::-;25151:32;;:::i;:::-;25192:65;25250:6;25242;25236:4;25192:65;:::i;:::-;25127:136;25074:189;;:::o;25269:186::-;25329:120;25346:3;25339:5;25336:14;25329:120;;;25400:39;25437:1;25430:5;25400:39;:::i;:::-;25373:1;25366:5;25362:13;25353:22;;25329:120;;;25269:186;;:::o;25461:543::-;25562:2;25557:3;25554:11;25551:446;;;25596:38;25628:5;25596:38;:::i;:::-;25680:29;25698:10;25680:29;:::i;:::-;25670:8;25666:44;25863:2;25851:10;25848:18;25845:49;;;25884:8;25869:23;;25845:49;25907:80;25963:22;25981:3;25963:22;:::i;:::-;25953:8;25949:37;25936:11;25907:80;:::i;:::-;25566:431;;25551:446;25461:543;;;:::o;26010:117::-;26064:8;26114:5;26108:4;26104:16;26083:37;;26010:117;;;;:::o;26133:169::-;26177:6;26210:51;26258:1;26254:6;26246:5;26243:1;26239:13;26210:51;:::i;:::-;26206:56;26291:4;26285;26281:15;26271:25;;26184:118;26133:169;;;;:::o;26307:295::-;26383:4;26529:29;26554:3;26548:4;26529:29;:::i;:::-;26521:37;;26591:3;26588:1;26584:11;26578:4;26575:21;26567:29;;26307:295;;;;:::o;26607:1395::-;26724:37;26757:3;26724:37;:::i;:::-;26826:18;26818:6;26815:30;26812:56;;;26848:18;;:::i;:::-;26812:56;26892:38;26924:4;26918:11;26892:38;:::i;:::-;26977:67;27037:6;27029;27023:4;26977:67;:::i;:::-;27071:1;27095:4;27082:17;;27127:2;27119:6;27116:14;27144:1;27139:618;;;;27801:1;27818:6;27815:77;;;27867:9;27862:3;27858:19;27852:26;27843:35;;27815:77;27918:67;27978:6;27971:5;27918:67;:::i;:::-;27912:4;27905:81;27774:222;27109:887;;27139:618;27191:4;27187:9;27179:6;27175:22;27225:37;27257:4;27225:37;:::i;:::-;27284:1;27298:208;27312:7;27309:1;27306:14;27298:208;;;27391:9;27386:3;27382:19;27376:26;27368:6;27361:42;27442:1;27434:6;27430:14;27420:24;;27489:2;27478:9;27474:18;27461:31;;27335:4;27332:1;27328:12;27323:17;;27298:208;;;27534:6;27525:7;27522:19;27519:179;;;27592:9;27587:3;27583:19;27577:26;27635:48;27677:4;27669:6;27665:17;27654:9;27635:48;:::i;:::-;27627:6;27620:64;27542:156;27519:179;27744:1;27740;27732:6;27728:14;27724:22;27718:4;27711:36;27146:611;;;27109:887;;26699:1303;;;26607:1395;;:::o;28008:168::-;28148:20;28144:1;28136:6;28132:14;28125:44;28008:168;:::o;28182:366::-;28324:3;28345:67;28409:2;28404:3;28345:67;:::i;:::-;28338:74;;28421:93;28510:3;28421:93;:::i;:::-;28539:2;28534:3;28530:12;28523:19;;28182:366;;;:::o;28554:419::-;28720:4;28758:2;28747:9;28743:18;28735:26;;28807:9;28801:4;28797:20;28793:1;28782:9;28778:17;28771:47;28835:131;28961:4;28835:131;:::i;:::-;28827:139;;28554:419;;;:::o;28979:170::-;29119:22;29115:1;29107:6;29103:14;29096:46;28979:170;:::o;29155:366::-;29297:3;29318:67;29382:2;29377:3;29318:67;:::i;:::-;29311:74;;29394:93;29483:3;29394:93;:::i;:::-;29512:2;29507:3;29503:12;29496:19;;29155:366;;;:::o;29527:419::-;29693:4;29731:2;29720:9;29716:18;29708:26;;29780:9;29774:4;29770:20;29766:1;29755:9;29751:17;29744:47;29808:131;29934:4;29808:131;:::i;:::-;29800:139;;29527:419;;;:::o;29952:171::-;30092:23;30088:1;30080:6;30076:14;30069:47;29952:171;:::o;30129:366::-;30271:3;30292:67;30356:2;30351:3;30292:67;:::i;:::-;30285:74;;30368:93;30457:3;30368:93;:::i;:::-;30486:2;30481:3;30477:12;30470:19;;30129:366;;;:::o;30501:419::-;30667:4;30705:2;30694:9;30690:18;30682:26;;30754:9;30748:4;30744:20;30740:1;30729:9;30725:17;30718:47;30782:131;30908:4;30782:131;:::i;:::-;30774:139;;30501:419;;;:::o;30926:148::-;31028:11;31065:3;31050:18;;30926:148;;;;:::o;31080:214::-;31220:66;31216:1;31208:6;31204:14;31197:90;31080:214;:::o;31300:402::-;31460:3;31481:85;31563:2;31558:3;31481:85;:::i;:::-;31474:92;;31575:93;31664:3;31575:93;:::i;:::-;31693:2;31688:3;31684:12;31677:19;;31300:402;;;:::o;31708:390::-;31814:3;31842:39;31875:5;31842:39;:::i;:::-;31897:89;31979:6;31974:3;31897:89;:::i;:::-;31890:96;;31995:65;32053:6;32048:3;32041:4;32034:5;32030:16;31995:65;:::i;:::-;32085:6;32080:3;32076:16;32069:23;;31818:280;31708:390;;;;:::o;32104:453::-;32244:66;32240:1;32232:6;32228:14;32221:90;32345:34;32340:2;32332:6;32328:15;32321:59;32414:34;32409:2;32401:6;32397:15;32390:59;32483:66;32478:2;32470:6;32466:15;32459:91;32104:453;:::o;32563:404::-;32723:3;32744:86;32826:3;32821;32744:86;:::i;:::-;32737:93;;32839;32928:3;32839:93;:::i;:::-;32957:3;32952;32948:13;32941:20;;32563:404;;;:::o;32973:416::-;33113:66;33109:1;33101:6;33097:14;33090:90;33214:66;33209:2;33201:6;33197:15;33190:91;33315:66;33310:2;33302:6;33298:15;33291:91;32973:416;:::o;33395:402::-;33555:3;33576:85;33658:2;33653:3;33576:85;:::i;:::-;33569:92;;33670:93;33759:3;33670:93;:::i;:::-;33788:2;33783:3;33779:12;33772:19;;33395:402;;;:::o;33803:1233::-;34286:3;34308:148;34452:3;34308:148;:::i;:::-;34301:155;;34473:95;34564:3;34555:6;34473:95;:::i;:::-;34466:102;;34585:148;34729:3;34585:148;:::i;:::-;34578:155;;34750:95;34841:3;34832:6;34750:95;:::i;:::-;34743:102;;34862:148;35006:3;34862:148;:::i;:::-;34855:155;;35027:3;35020:10;;33803:1233;;;;;:::o;35042:179::-;35182:31;35178:1;35170:6;35166:14;35159:55;35042:179;:::o;35227:402::-;35387:3;35408:85;35490:2;35485:3;35408:85;:::i;:::-;35401:92;;35502:93;35591:3;35502:93;:::i;:::-;35620:2;35615:3;35611:12;35604:19;;35227:402;;;:::o;35635:541::-;35868:3;35890:148;36034:3;35890:148;:::i;:::-;35883:155;;36055:95;36146:3;36137:6;36055:95;:::i;:::-;36048:102;;36167:3;36160:10;;35635:541;;;;:::o;36182:94::-;36215:8;36263:5;36259:2;36255:14;36234:35;;36182:94;;;:::o;36282:::-;36321:7;36350:20;36364:5;36350:20;:::i;:::-;36339:31;;36282:94;;;:::o;36382:100::-;36421:7;36450:26;36470:5;36450:26;:::i;:::-;36439:37;;36382:100;;;:::o;36488:157::-;36593:45;36613:24;36631:5;36613:24;:::i;:::-;36593:45;:::i;:::-;36588:3;36581:58;36488:157;;:::o;36651:154::-;36791:6;36787:1;36779:6;36775:14;36768:30;36651:154;:::o;36811:400::-;36971:3;36992:84;37074:1;37069:3;36992:84;:::i;:::-;36985:91;;37085:93;37174:3;37085:93;:::i;:::-;37203:1;37198:3;37194:11;37187:18;;36811:400;;;:::o;37217:79::-;37256:7;37285:5;37274:16;;37217:79;;;:::o;37302:157::-;37407:45;37427:24;37445:5;37427:24;:::i;:::-;37407:45;:::i;:::-;37402:3;37395:58;37302:157;;:::o;37465:823::-;37754:3;37769:75;37840:3;37831:6;37769:75;:::i;:::-;37869:2;37864:3;37860:12;37853:19;;37889:148;38033:3;37889:148;:::i;:::-;37882:155;;38047:75;38118:3;38109:6;38047:75;:::i;:::-;38147:2;38142:3;38138:12;38131:19;;38167:95;38258:3;38249:6;38167:95;:::i;:::-;38160:102;;38279:3;38272:10;;37465:823;;;;;;:::o;38294:98::-;38345:6;38379:5;38373:12;38363:22;;38294:98;;;:::o;38398:168::-;38481:11;38515:6;38510:3;38503:19;38555:4;38550:3;38546:14;38531:29;;38398:168;;;;:::o;38572:373::-;38658:3;38686:38;38718:5;38686:38;:::i;:::-;38740:70;38803:6;38798:3;38740:70;:::i;:::-;38733:77;;38819:65;38877:6;38872:3;38865:4;38858:5;38854:16;38819:65;:::i;:::-;38909:29;38931:6;38909:29;:::i;:::-;38904:3;38900:39;38893:46;;38662:283;38572:373;;;;:::o;38951:640::-;39146:4;39184:3;39173:9;39169:19;39161:27;;39198:71;39266:1;39255:9;39251:17;39242:6;39198:71;:::i;:::-;39279:72;39347:2;39336:9;39332:18;39323:6;39279:72;:::i;:::-;39361;39429:2;39418:9;39414:18;39405:6;39361:72;:::i;:::-;39480:9;39474:4;39470:20;39465:2;39454:9;39450:18;39443:48;39508:76;39579:4;39570:6;39508:76;:::i;:::-;39500:84;;38951:640;;;;;;;:::o;39597:141::-;39653:5;39684:6;39678:13;39669:22;;39700:32;39726:5;39700:32;:::i;:::-;39597:141;;;;:::o;39744:349::-;39813:6;39862:2;39850:9;39841:7;39837:23;39833:32;39830:119;;;39868:79;;:::i;:::-;39830:119;39988:1;40013:63;40068:7;40059:6;40048:9;40044:22;40013:63;:::i;:::-;40003:73;;39959:127;39744:349;;;;:::o;40099:180::-;40147:77;40144:1;40137:88;40244:4;40241:1;40234:15;40268:4;40265:1;40258:15;40285:233;40324:3;40347:24;40365:5;40347:24;:::i;:::-;40338:33;;40393:66;40386:5;40383:77;40380:103;;40463:18;;:::i;:::-;40380:103;40510:1;40503:5;40499:13;40492:20;;40285:233;;;:::o;40524:180::-;40572:77;40569:1;40562:88;40669:4;40666:1;40659:15;40693:4;40690:1;40683:15;40710:185;40750:1;40767:20;40785:1;40767:20;:::i;:::-;40762:25;;40801:20;40819:1;40801:20;:::i;:::-;40796:25;;40840:1;40830:35;;40845:18;;:::i;:::-;40830:35;40887:1;40884;40880:9;40875:14;;40710:185;;;;:::o;40901:194::-;40941:4;40961:20;40979:1;40961:20;:::i;:::-;40956:25;;40995:20;41013:1;40995:20;:::i;:::-;40990:25;;41039:1;41036;41032:9;41024:17;;41063:1;41057:4;41054:11;41051:37;;;41068:18;;:::i;:::-;41051:37;40901:194;;;;:::o;41101:176::-;41133:1;41150:20;41168:1;41150:20;:::i;:::-;41145:25;;41184:20;41202:1;41184:20;:::i;:::-;41179:25;;41223:1;41213:35;;41228:18;;:::i;:::-;41213:35;41269:1;41266;41262:9;41257:14;;41101:176;;;;:::o;41283:191::-;41323:3;41342:20;41360:1;41342:20;:::i;:::-;41337:25;;41376:20;41394:1;41376:20;:::i;:::-;41371:25;;41419:1;41416;41412:9;41405:16;;41440:3;41437:1;41434:10;41431:36;;;41447:18;;:::i;:::-;41431:36;41283:191;;;;:::o;41480:410::-;41520:7;41543:20;41561:1;41543:20;:::i;:::-;41538:25;;41577:20;41595:1;41577:20;:::i;:::-;41572:25;;41632:1;41629;41625:9;41654:30;41672:11;41654:30;:::i;:::-;41643:41;;41833:1;41824:7;41820:15;41817:1;41814:22;41794:1;41787:9;41767:83;41744:139;;41863:18;;:::i;:::-;41744:139;41528:362;41480:410;;;;:::o;41896:180::-;41944:77;41941:1;41934:88;42041:4;42038:1;42031:15;42065:4;42062:1;42055:15;42082:180;42130:77;42127:1;42120:88;42227:4;42224:1;42217:15;42251:4;42248:1;42241:15;42268:77;42305:7;42334:5;42323:16;;42268:77;;;:::o;42351:118::-;42438:24;42456:5;42438:24;:::i;:::-;42433:3;42426:37;42351:118;;:::o;42475:222::-;42568:4;42606:2;42595:9;42591:18;42583:26;;42619:71;42687:1;42676:9;42672:17;42663:6;42619:71;:::i;:::-;42475:222;;;;:::o;42703:86::-;42738:7;42778:4;42771:5;42767:16;42756:27;;42703:86;;;:::o;42795:112::-;42878:22;42894:5;42878:22;:::i;:::-;42873:3;42866:35;42795:112;;:::o;42913:545::-;43086:4;43124:3;43113:9;43109:19;43101:27;;43138:71;43206:1;43195:9;43191:17;43182:6;43138:71;:::i;:::-;43219:68;43283:2;43272:9;43268:18;43259:6;43219:68;:::i;:::-;43297:72;43365:2;43354:9;43350:18;43341:6;43297:72;:::i;:::-;43379;43447:2;43436:9;43432:18;43423:6;43379:72;:::i;:::-;42913:545;;;;;;;:::o
Swarm Source
ipfs://06acf36b1e4c2d87474a555bd7329253049a1f6cffcc07a326b894e304abd56b
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in MON
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.