Source Code
Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,621 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Approval For... | 59790596 | 19 days ago | IN | 0 S | 0.00146894 | ||||
| Set Approval For... | 59522519 | 23 days ago | IN | 0 S | 0.00133975 | ||||
| Set Approval For... | 59522500 | 23 days ago | IN | 0 S | 0.00233375 | ||||
| Set Approval For... | 59141078 | 28 days ago | IN | 0 S | 0.0024504 | ||||
| Set Approval For... | 59137076 | 28 days ago | IN | 0 S | 0.00233375 | ||||
| Set Approval For... | 59109546 | 29 days ago | IN | 0 S | 0.00269544 | ||||
| Safe Transfer Fr... | 59109406 | 29 days ago | IN | 0 S | 0.0051046 | ||||
| Set Approval For... | 59078491 | 29 days ago | IN | 0 S | 0.00154797 | ||||
| Set Approval For... | 59078464 | 29 days ago | IN | 0 S | 0.00269544 | ||||
| Set Approval For... | 59012293 | 30 days ago | IN | 0 S | 0.00126215 | ||||
| Set Approval For... | 59011199 | 30 days ago | IN | 0 S | 0.00141552 | ||||
| Set Approval For... | 59006646 | 30 days ago | IN | 0 S | 0.00146894 | ||||
| Set Approval For... | 58817016 | 32 days ago | IN | 0 S | 0.0024504 | ||||
| Safe Transfer Fr... | 58604597 | 35 days ago | IN | 0 S | 0.00466298 | ||||
| Set Approval For... | 58398306 | 37 days ago | IN | 0 S | 0.00233375 | ||||
| Approve | 57697472 | 46 days ago | IN | 0 S | 0.00262879 | ||||
| Safe Transfer Fr... | 57678956 | 46 days ago | IN | 0 S | 0.004323 | ||||
| Approve | 57399422 | 49 days ago | IN | 0 S | 0.00245515 | ||||
| Approve | 56780503 | 57 days ago | IN | 0 S | 0.00245515 | ||||
| Approve | 56780470 | 57 days ago | IN | 0 S | 0.00245455 | ||||
| Approve | 56780234 | 57 days ago | IN | 0 S | 0.00245455 | ||||
| Approve | 56564463 | 60 days ago | IN | 0 S | 0.0030927 | ||||
| Approve | 56462778 | 61 days ago | IN | 0 S | 0.00262879 | ||||
| Safe Transfer Fr... | 56458164 | 61 days ago | IN | 0 S | 0.004391 | ||||
| Approve | 56458154 | 61 days ago | IN | 0 S | 0.00245455 |
Latest 9 internal transactions
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Razors
Compiler Version
v0.8.22+commit.4fc1097e
Contract Source Code (Solidity)
/**
*Submitted for verification at SonicScan.org on 2025-04-29
*/
// File: @openzeppelin/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/* %%% %%% %%
% %% %%% % %%%%%% %% %% %%% %%% %
% %%%%%%%%%%%%%%% %%%%% % %% %%%%%%%%%%% %%%%%%%%%%%% %%% %%%%% %%
%% %%% %% %% %%% % %%%%%%% %%
% %%%% %%% % % %%% %%%% %% %%
%% %%%% %%% %% %%%% %% %% %% %%%% %% %%%%% %%
% %%%% %%% %%%% %%%%% %% %%%% %% %%%%% %%%% %%
%% %% %%%%% %%%% %% %%%%% %% %%%% %%%% %%%
%% %%%%% %% %% %%%%% %% %%%%%%% %%
%% % %%%% %% %%% %%%% %% %%% %% %%%%%% %%
%% %%%% %% %%%%%% % % %% %%% %%% %%%% %%% %%%% %%
%% %%% % %%%%%% % %% %%% %%%% %%%% %%% %%
%% %%% % %%% %%%%%%%%%%% %%% %%% %% %%%%% %%%%% %%% %%
%% %%% %%%%%%%%%% %%%%%% %%%%%%%%%%%%%% %%%%%%%%%% %% %%% %%
%% %%% %%% %% % %% %%% %%
% %%%% %%% %%% %%%
%% %%%%% %% %%% %%% %%
%% %%%%%%% %%% %%% %%% %%
%% %% %%%%% %%%%%%%%%%%%% %%
%% %% %%%%%% %%
%%%%% %%%%%
*/
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: @openzeppelin/contracts/token/ERC721/IERC721.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
/**
* @dev Required interface of an ERC-721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC-721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}
// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC-721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
// File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
// File: @openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/utils/ERC721Utils.sol)
pragma solidity ^0.8.20;
/**
* @dev Library that provide common ERC-721 utility functions.
*
* See https://eips.ethereum.org/EIPS/eip-721[ERC-721].
*
* _Available since v5.1._
*/
library ERC721Utils {
/**
* @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received}
* on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
*
* The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
* Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept
* the transfer.
*/
function checkOnERC721Received(
address operator,
address from,
address to,
uint256 tokenId,
bytes memory data
) internal {
if (to.code.length > 0) {
try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
// Token rejected
revert IERC721Errors.ERC721InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
// non-IERC721Receiver implementer
revert IERC721Errors.ERC721InvalidReceiver(to);
} else {
assembly ("memory-safe") {
revert(add(32, reason), mload(reason))
}
}
}
}
}
}
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// File: @openzeppelin/contracts/utils/Panic.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* // Use any of the declared internal constants
* function foo() { Panic.GENERIC.panic(); }
*
* // Alternatively
* function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
*
* _Available since v5.1._
*/
// slither-disable-next-line unused-state
library Panic {
/// @dev generic / unspecified error
uint256 internal constant GENERIC = 0x00;
/// @dev used by the assert() builtin
uint256 internal constant ASSERT = 0x01;
/// @dev arithmetic underflow or overflow
uint256 internal constant UNDER_OVERFLOW = 0x11;
/// @dev division or modulo by zero
uint256 internal constant DIVISION_BY_ZERO = 0x12;
/// @dev enum conversion error
uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
/// @dev invalid encoding in storage
uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
/// @dev empty array pop
uint256 internal constant EMPTY_ARRAY_POP = 0x31;
/// @dev array out of bounds access
uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
/// @dev resource error (too large allocation or too large array)
uint256 internal constant RESOURCE_ERROR = 0x41;
/// @dev calling invalid internal function
uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
/// @dev Reverts with a panic code. Recommended to use with
/// the internal constants with predefined codes.
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}
// File: @openzeppelin/contracts/utils/math/SafeCast.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}
// File: @openzeppelin/contracts/utils/math/Math.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2²⁵⁶ + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= prod1) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
uint256 exp;
unchecked {
exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);
value >>= exp;
result += exp;
exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);
value >>= exp;
result += exp;
exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);
value >>= exp;
result += exp;
exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);
value >>= exp;
result += exp;
exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);
value >>= exp;
result += exp;
exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);
value >>= exp;
result += exp;
exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);
value >>= exp;
result += exp;
result += SafeCast.toUint(value > 1);
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
uint256 isGt;
unchecked {
isGt = SafeCast.toUint(value > (1 << 128) - 1);
value >>= isGt * 128;
result += isGt * 16;
isGt = SafeCast.toUint(value > (1 << 64) - 1);
value >>= isGt * 64;
result += isGt * 8;
isGt = SafeCast.toUint(value > (1 << 32) - 1);
value >>= isGt * 32;
result += isGt * 4;
isGt = SafeCast.toUint(value > (1 << 16) - 1);
value >>= isGt * 16;
result += isGt * 2;
result += SafeCast.toUint(value > (1 << 8) - 1);
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}
// File: @openzeppelin/contracts/utils/math/SignedMath.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
}
}
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
// Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
// taking advantage of the most significant (or "sign" bit) in two's complement representation.
// This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
// the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
int256 mask = n >> 255;
// A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
return uint256((n + mask) ^ mask);
}
}
}
// File: @openzeppelin/contracts/utils/Strings.sol
// OpenZeppelin Contracts (last updated v5.2.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
/**
* @dev String operations.
*/
library Strings {
using SafeCast for *;
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev The string being parsed contains characters that are not in scope of the given base.
*/
error StringsInvalidChar();
/**
* @dev The string being parsed is not a properly formatted address.
*/
error StringsInvalidAddressFormat();
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly ("memory-safe") {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly ("memory-safe") {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
* representation, according to EIP-55.
*/
function toChecksumHexString(address addr) internal pure returns (string memory) {
bytes memory buffer = bytes(toHexString(addr));
// hash the hex part of buffer (skip length + 2 bytes, length 40)
uint256 hashValue;
assembly ("memory-safe") {
hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
}
for (uint256 i = 41; i > 1; --i) {
// possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
// case shift by xoring with 0x20
buffer[i] ^= 0x20;
}
hashValue >>= 4;
}
return string(buffer);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
/**
* @dev Parse a decimal string and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input) internal pure returns (uint256) {
return parseUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
uint256 result = 0;
for (uint256 i = begin; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 9) return (false, 0);
result *= 10;
result += chr;
}
return (true, result);
}
/**
* @dev Parse a decimal string and returns the value as a `int256`.
*
* Requirements:
* - The string must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input) internal pure returns (int256) {
return parseInt(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {
(bool success, int256 value) = tryParseInt(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
* the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {
return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
}
uint256 private constant ABS_MIN_INT256 = 2 ** 255;
/**
* @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character or if the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, int256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseIntUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseIntUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, int256 value) {
bytes memory buffer = bytes(input);
// Check presence of a negative sign.
bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
bool positiveSign = sign == bytes1("+");
bool negativeSign = sign == bytes1("-");
uint256 offset = (positiveSign || negativeSign).toUint();
(bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);
if (absSuccess && absValue < ABS_MIN_INT256) {
return (true, negativeSign ? -int256(absValue) : int256(absValue));
} else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
return (true, type(int256).min);
} else return (false, 0);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input) internal pure returns (uint256) {
return parseHexUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseHexUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
* invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseHexUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseHexUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
// skip 0x prefix if present
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 offset = hasPrefix.toUint() * 2;
uint256 result = 0;
for (uint256 i = begin + offset; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 15) return (false, 0);
result *= 16;
unchecked {
// Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
// This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked.
result += chr;
}
}
return (true, result);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input) internal pure returns (address) {
return parseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {
(bool success, address value) = tryParseAddress(input, begin, end);
if (!success) revert StringsInvalidAddressFormat();
return value;
}
/**
* @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
* formatted address. See {parseAddress} requirements.
*/
function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
return tryParseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
* formatted address. See {parseAddress} requirements.
*/
function tryParseAddress(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, address value) {
if (end > bytes(input).length || begin > end) return (false, address(0));
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 expectedLength = 40 + hasPrefix.toUint() * 2;
// check that input is the correct length
if (end - begin == expectedLength) {
// length guarantees that this does not overflow, and value is at most type(uint160).max
(bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);
return (s, address(uint160(v)));
} else {
return (false, address(0));
}
}
function _tryParseChr(bytes1 chr) private pure returns (uint8) {
uint8 value = uint8(chr);
// Try to parse `chr`:
// - Case 1: [0-9]
// - Case 2: [a-f]
// - Case 3: [A-F]
// - otherwise not supported
unchecked {
if (value > 47 && value < 58) value -= 48;
else if (value > 96 && value < 103) value -= 87;
else if (value > 64 && value < 71) value -= 55;
else return type(uint8).max;
}
return value;
}
/**
* @dev Reads a bytes32 from a bytes array without bounds checking.
*
* NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
* assembly block as such would prevent some optimizations.
*/
function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
// This is not memory safe in the general case, but all calls to this private function are within bounds.
assembly ("memory-safe") {
value := mload(add(buffer, add(0x20, offset)))
}
}
}
// File: @openzeppelin/contracts/utils/introspection/ERC165.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
// File: @openzeppelin/contracts/token/ERC721/ERC721.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
mapping(uint256 tokenId => address) private _owners;
mapping(address owner => uint256) private _balances;
mapping(uint256 tokenId => address) private _tokenApprovals;
mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual returns (uint256) {
if (owner == address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual returns (address) {
return _requireOwned(tokenId);
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
_requireOwned(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual {
_approve(to, tokenId, _msgSender());
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual returns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
transferFrom(from, to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*
* IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
* core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances
* consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
* `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
*/
function _getApproved(uint256 tokenId) internal view virtual returns (address) {
return _tokenApprovals[tokenId];
}
/**
* @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
return
spender != address(0) &&
(owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
/**
* @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
* Reverts if:
* - `spender` does not have approval from `owner` for `tokenId`.
* - `spender` does not have approval to manage all of `owner`'s assets.
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
* a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
*
* WARNING: Increasing an account's balance using this function tends to be paired with an override of the
* {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
* remain consistent with one another.
*/
function _increaseBalance(address account, uint128 value) internal virtual {
unchecked {
_balances[account] += value;
}
}
/**
* @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
* (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that
* `auth` is either the owner of the token, or approved to operate on the token (by the owner).
*
* Emits a {Transfer} event.
*
* NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
address from = _ownerOf(tokenId);
// Perform (optional) operator check
if (auth != address(0)) {
_checkAuthorized(from, auth, tokenId);
}
// Execute the update
if (from != address(0)) {
// Clear approval. No need to re-authorize or emit the Approval event
_approve(address(0), tokenId, address(0), false);
unchecked {
_balances[from] -= 1;
}
}
if (to != address(0)) {
unchecked {
_balances[to] += 1;
}
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
return from;
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner != address(0)) {
revert ERC721InvalidSender(address(0));
}
}
/**
* @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal {
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
* are aware of the ERC-721 standard to prevent tokens from being forever locked.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is like {safeTransferFrom} in the sense that it invokes
* {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `tokenId` token must exist and be owned by `from`.
* - `to` cannot be the zero address.
* - `from` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId) internal {
_safeTransfer(from, to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
* either the owner of the token, or approved to operate on all tokens held by this owner.
*
* Emits an {Approval} event.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address to, uint256 tokenId, address auth) internal {
_approve(to, tokenId, auth, true);
}
/**
* @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
* emitted in the context of transfers.
*/
function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
// Avoid reading the owner unless necessary
if (emitEvent || auth != address(0)) {
address owner = _requireOwned(tokenId);
// We do not use _isAuthorized because single-token approvals should not be able to call approve
if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
_tokenApprovals[tokenId] = to;
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Requirements:
* - operator can't be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC721InvalidOperator(operator);
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
* Returns the owner.
*
* Overrides to ownership logic should be done to {_ownerOf}.
*/
function _requireOwned(uint256 tokenId) internal view returns (address) {
address owner = _ownerOf(tokenId);
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
}
// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Burnable.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 Burnable Token
* @dev ERC-721 Token that can be burned (destroyed).
*/
abstract contract ERC721Burnable is Context, ERC721 {
/**
* @dev Burns `tokenId`. See {ERC721-_burn}.
*
* Requirements:
*
* - The caller must own `tokenId` or be an approved operator.
*/
function burn(uint256 tokenId) public virtual {
// 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.
_update(address(0), tokenId, _msgSender());
}
}
// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Enumerable.sol)
pragma solidity ^0.8.20;
/**
* @dev This implements an optional extension of {ERC721} defined in the ERC that adds enumerability
* of all the token ids in the contract as well as all token ids owned by each account.
*
* CAUTION: {ERC721} extensions that implement custom `balanceOf` logic, such as {ERC721Consecutive},
* interfere with enumerability and should not be used together with {ERC721Enumerable}.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens;
mapping(uint256 tokenId => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 tokenId => uint256) private _allTokensIndex;
/**
* @dev An `owner`'s token query was out of bounds for `index`.
*
* NOTE: The owner being `address(0)` indicates a global out of bounds index.
*/
error ERC721OutOfBoundsIndex(address owner, uint256 index);
/**
* @dev Batch mint is not allowed.
*/
error ERC721EnumerableForbiddenBatchMint();
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
if (index >= balanceOf(owner)) {
revert ERC721OutOfBoundsIndex(owner, index);
}
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual returns (uint256) {
if (index >= totalSupply()) {
revert ERC721OutOfBoundsIndex(address(0), index);
}
return _allTokens[index];
}
/**
* @dev See {ERC721-_update}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
address previousOwner = super._update(to, tokenId, auth);
if (previousOwner == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_removeTokenFromOwnerEnumeration(previousOwner, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_addTokenToOwnerEnumeration(to, tokenId);
}
return previousOwner;
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = balanceOf(to) - 1;
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = balanceOf(from);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
mapping(uint256 index => uint256) storage _ownedTokensByOwner = _ownedTokens[from];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokensByOwner[lastTokenIndex];
_ownedTokensByOwner[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokensByOwner[lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
/**
* See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
*/
function _increaseBalance(address account, uint128 amount) internal virtual override {
if (amount > 0) {
revert ERC721EnumerableForbiddenBatchMint();
}
super._increaseBalance(account, amount);
}
}
// File: @openzeppelin/contracts/utils/Pausable.sol
// OpenZeppelin Contracts (last updated v5.0.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 Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @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: @openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Pausable.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC-721 token with pausable token transfers, minting and burning.
*
* Useful for scenarios such as preventing trades until the end of an evaluation
* period, or having an emergency switch for freezing all token transfers in the
* event of a large bug.
*
* IMPORTANT: This contract does not include public pause and unpause functions. In
* addition to inheriting this contract, you must define both functions, invoking the
* {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate
* access control, e.g. using {AccessControl} or {Ownable}. Not doing so will
* make the contract pause mechanism of the contract unreachable, and thus unusable.
*/
abstract contract ERC721Pausable is ERC721, Pausable {
/**
* @dev See {ERC721-_update}.
*
* Requirements:
*
* - the contract must not be paused.
*/
function _update(
address to,
uint256 tokenId,
address auth
) internal virtual override whenNotPaused returns (address) {
return super._update(to, tokenId, auth);
}
}
// File: @openzeppelin/contracts/interfaces/IERC165.sol
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
// File: @openzeppelin/contracts/interfaces/IERC721.sol
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721.sol)
pragma solidity ^0.8.20;
// File: @openzeppelin/contracts/interfaces/IERC4906.sol
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4906.sol)
pragma solidity ^0.8.20;
/// @title ERC-721 Metadata Update Extension
interface IERC4906 is IERC165, IERC721 {
/// @dev This event emits when the metadata of a token is changed.
/// So that the third-party platforms such as NFT market could
/// timely update the images and related attributes of the NFT.
event MetadataUpdate(uint256 _tokenId);
/// @dev This event emits when the metadata of a range of tokens is changed.
/// So that the third-party platforms such as NFT market could
/// timely update the images and related attributes of the NFTs.
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}
// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC721/extensions/ERC721URIStorage.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC-721 token with storage based token URI management.
*/
abstract contract ERC721URIStorage is IERC4906, ERC721 {
using Strings for uint256;
// Interface ID as defined in ERC-4906. This does not correspond to a traditional interface ID as ERC-4906 only
// defines events and does not include any external function.
bytes4 private constant ERC4906_INTERFACE_ID = bytes4(0x49064906);
// Optional mapping for token URIs
mapping(uint256 tokenId => string) private _tokenURIs;
/**
* @dev See {IERC165-supportsInterface}
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, IERC165) returns (bool) {
return interfaceId == ERC4906_INTERFACE_ID || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
_requireOwned(tokenId);
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
// If there is no base URI, return the token URI.
if (bytes(base).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via string.concat).
if (bytes(_tokenURI).length > 0) {
return string.concat(base, _tokenURI);
}
return super.tokenURI(tokenId);
}
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Emits {IERC4906-MetadataUpdate}.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
_tokenURIs[tokenId] = _tokenURI;
emit MetadataUpdate(tokenId);
}
}
// 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: Razors.sol
/* %%% %%% %%
% %% %%% % %%%%%% %% %% %%% %%% %
% %%%%%%%%%%%%%%% %%%%% % %% %%%%%%%%%%% %%%%%%%%%%%% %%% %%%%% %%
%% %%% %% %% %%% % %%%%%%% %%
% %%%% %%% % % %%% %%%% %% %%
%% %%%% %%% %% %%%% %% %% %% %%%% %% %%%%% %%
% %%%% %%% %%%% %%%%% %% %%%% %% %%%%% %%%% %%
%% %% %%%%% %%%% %% %%%%% %% %%%% %%%% %%%
%% %%%%% %% %% %%%%% %% %%%%%%% %%
%% % %%%% %% %%% %%%% %% %%% %% %%%%%% %%
%% %%%% %% %%%%%% % % %% %%% %%% %%%% %%% %%%% %%
%% %%% % %%%%%% % %% %%% %%%% %%%% %%% %%
%% %%% % %%% %%%%%%%%%%% %%% %%% %% %%%%% %%%%% %%% %%
%% %%% %%%%%%%%%% %%%%%% %%%%%%%%%%%%%% %%%%%%%%%% %% %%% %%
%% %%% %%% %% % %% %%% %%
% %%%% %%% %%% %%%
%% %%%%% %% %%% %%% %%
%% %%%%%%% %%% %%% %%% %%
%% %% %%%%% %%%%%%%%%%%%% %%
%% %% %%%%%% %%
%%%%% %%%%%
*/
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.22;
// import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Razors is
ERC721,
ERC721Enumerable,
ERC721URIStorage,
ERC721Pausable,
Ownable,
ERC721Burnable
{
using Strings for uint256; // Use Strings library for uint256
uint256 private _nextTokenId;
// --- State Variables for Whitelist and Phases ---
mapping(address => bool) private _isWhitelisted;
mapping(address => bool) private _hasWhitelistedMinted; // Tracks if a whitelisted address used their mint
bool public isPublicMintActive = false; // Flag to control minting phases
uint256 public maxSupply; // Maximum number of NFTs
uint256 public publicMintLimitPerTx = 10; // Default limit per transaction during public sale
uint256 public constant WHITELIST_MINT_LIMIT_PER_ADDRESS = 1; // Whitelist limit is always 1
uint256 public MINT_PRICE = 25 ether;
string private _baseTokenURI;
// --- Custom Errors ---
error NotWhitelisted();
error AlreadyWhitelistedMinted();
error WhitelistNotActive();
error PublicSaleNotActive();
error InvalidMintQuantity();
error MaxSupplyReached();
error QuantityExceedsPublicLimit();
error InsufficientPayment();
error ContractPaused();
constructor(
uint256 _maxSupply,
string memory initialBaseURI
) ERC721("Razors", "RZS") Ownable(msg.sender) {
maxSupply = _maxSupply; // Set total supply in constructor
_baseTokenURI = initialBaseURI;
}
// --- Owner Functions ---
// @notice Sets the mint price for the contract.
// @param _newPrice The new mint price in wei.
function setMintPrice(uint256 _newPrice) external onlyOwner {
MINT_PRICE = _newPrice;
}
/// @notice Adds a single address to the whitelist.
/// @param addr The address to whitelist.
function addAddressToWhitelist(address addr) public onlyOwner {
_isWhitelisted[addr] = true;
}
/// @notice Adds multiple addresses to the whitelist.
/// @param addrs An array of addresses to whitelist.
/// @dev Be mindful of gas limits when adding a large number of addresses.
/// You may need to split your 1500 addresses into multiple transactions.
function addAddressesToWhitelist(
address[] calldata addrs
) public onlyOwner {
for (uint i = 0; i < addrs.length; i++) {
_isWhitelisted[addrs[i]] = true;
}
}
/// @notice Allows the owner to set or update a token's URI
/// @param tokenId The token ID to update
/// @param newURI The new URI string
function setTokenURI(
uint256 tokenId,
string memory newURI
) public onlyOwner {
if (_ownerOf(tokenId) == address(0)) {
revert IERC721Errors.ERC721NonexistentToken(tokenId);
}
_setTokenURI(tokenId, newURI);
}
/// @notice Removes an address from the whitelist.
/// @param addr The address to remove.
function removeAddressFromWhitelist(address addr) public onlyOwner {
_isWhitelisted[addr] = false;
// Optionally reset _hasWhitelistedMinted if they are removed before minting
// _hasWhitelistedMinted[addr] = false;
}
/// @notice Toggles between whitelist and public minting phases
/// @dev Only callable by contract owner
function togglePublicMint() public onlyOwner {
isPublicMintActive = !isPublicMintActive;
}
/// @notice Sets the total maximum supply of tokens. Can only be set once or increased.
/// @param _maxSupply The new maximum supply.
function setMaxSupply(uint256 _maxSupply) public onlyOwner {
require(_maxSupply >= totalSupply(), "New supply less than current");
maxSupply = _maxSupply;
}
/// @notice Sets the maximum number of tokens a user can mint in a single transaction during the public phase.
/// @param limit The new limit per transaction.
function setPublicMintLimitPerTx(uint256 limit) public onlyOwner {
publicMintLimitPerTx = limit;
}
/// @notice Allows the owner to withdraw collected funds
function withdraw() public onlyOwner {
uint256 balance = address(this).balance;
require(balance > 0, "No funds to withdraw");
(bool success, ) = payable(owner()).call{value: balance}("");
require(success, "Withdrawal failed");
}
// --- Public Mint Function ---
/// @notice Allows users to mint tokens based on the current phase (whitelist or public).
/// @param quantity The number of tokens to mint in this transaction.
function mint(uint256 quantity) public payable {
// Check if contract is paused
if (paused()) revert ContractPaused();
// Check total supply limit
if (totalSupply() + quantity > maxSupply) {
revert MaxSupplyReached();
}
// Payment check - owner mints for free
if (msg.sender != owner()) {
if (msg.value < MINT_PRICE * quantity) {
revert InsufficientPayment();
}
}
// --- Whitelist Phase Logic ---
if (!isPublicMintActive) {
// Check if sender is whitelisted
if (!_isWhitelisted[msg.sender]) {
revert NotWhitelisted();
}
// Check if sender already minted during whitelist
if (_hasWhitelistedMinted[msg.sender]) {
revert AlreadyWhitelistedMinted();
}
// Whitelist mint quantity must be exactly 1
if (quantity != WHITELIST_MINT_LIMIT_PER_ADDRESS) {
revert InvalidMintQuantity();
}
// Mark address as having minted during whitelist
_hasWhitelistedMinted[msg.sender] = true;
}
// --- Public Phase Logic ---
else {
// Check public sale transaction limit
if (quantity == 0 || quantity > publicMintLimitPerTx) {
revert QuantityExceedsPublicLimit();
}
// No per-address limit in public phase
}
// --- Minting Process ---
for (uint256 i = 0; i < quantity; i++) {
uint256 tokenId = _nextTokenId++;
// Double-check supply limit during minting loop
if (tokenId >= maxSupply) {
// This shouldn't happen if the initial check passes, but is a safeguard
revert MaxSupplyReached();
}
_safeMint(msg.sender, tokenId);
// Token URI is handled by the overridden tokenURI function below using base + ID
}
}
// --- Owner-only Safe Mint (Keep separate for airdrops etc.) ---
// Note: Removed 'uri' parameter as tokenURI now uses base + ID.
// If you need to set individual URIs for owner mints, add 'string memory uri' parameter back
// and call _setTokenURI(tokenId, uri); after _safeMint.
function safeMint(address to) public onlyOwner returns (uint256) {
// Check if contract is paused
if (paused()) revert ContractPaused();
uint256 tokenId = _nextTokenId++;
if (tokenId >= maxSupply) revert MaxSupplyReached();
_safeMint(to, tokenId);
// _setTokenURI is NOT called here, relying on tokenURI override
return tokenId;
}
// --- Batch Mint for Owner Distribution ---
/// @notice Allows the owner to mint multiple NFTs at once for distribution
/// @param to The address to receive the NFTs
/// @param quantity The number of NFTs to mint
function batchMint(
address to,
uint256 quantity
) public onlyOwner returns (uint256[] memory) {
// Check if contract is paused
if (paused()) revert ContractPaused();
require(totalSupply() + quantity <= maxSupply, "Exceeds max supply");
uint256[] memory tokenIds = new uint256[](quantity);
for (uint256 i = 0; i < quantity; i++) {
uint256 tokenId = _nextTokenId++;
_safeMint(to, tokenId);
tokenIds[i] = tokenId;
}
return tokenIds;
}
// --- View Functions ---
/// @notice Checks if an address is currently whitelisted.
/// @param addr The address to check.
/// @return True if the address is whitelisted, false otherwise.
function isWhitelisted(address addr) public view returns (bool) {
return _isWhitelisted[addr];
}
/// @notice Checks if a whitelisted address has already minted during the whitelist phase.
/// @param addr The address to check.
/// @return True if the whitelisted address has minted, false otherwise.
function hasWhitelistedMinted(address addr) public view returns (bool) {
return _hasWhitelistedMinted[addr];
}
/// @notice Checks the current minting phase.
/// @return True if in whitelist phase, false if in public phase.
function isWhitelistActive() public view returns (bool) {
return !isPublicMintActive;
}
// --- Override Functions ---
function _baseURI() internal view override returns (string memory) {
return _baseTokenURI;
}
function setBaseURI(string memory newBaseURI) public onlyOwner {
_baseTokenURI = newBaseURI;
}
function tokenURI(
uint256 tokenId
) public view override(ERC721, ERC721URIStorage) returns (string memory) {
if (_ownerOf(tokenId) == address(0)) {
revert IERC721Errors.ERC721NonexistentToken(tokenId);
}
string memory storedTokenURI = super.tokenURI(tokenId);
if (bytes(storedTokenURI).length > 0) {
return storedTokenURI; // Return custom per-token URI if set
}
string memory base = _baseURI();
return string(abi.encodePacked(base, tokenId.toString(), ".json")); // Otherwise fallback to base URI
}
// The following functions are overrides required by Solidity.
function _update(
address to,
uint256 tokenId,
address auth
)
internal
override(ERC721, ERC721Enumerable, ERC721Pausable)
returns (address)
{
return super._update(to, tokenId, auth);
}
function _increaseBalance(
address account,
uint128 value
) internal override(ERC721, ERC721Enumerable) {
super._increaseBalance(account, value);
}
function supportsInterface(
bytes4 interfaceId
)
public
view
override(ERC721, ERC721Enumerable, ERC721URIStorage)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
// Keep Pause/Unpause functions as they are useful
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"_maxSupply","type":"uint256"},{"internalType":"string","name":"initialBaseURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyWhitelistedMinted","type":"error"},{"inputs":[],"name":"ContractPaused","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":[],"name":"InsufficientPayment","type":"error"},{"inputs":[],"name":"InvalidMintQuantity","type":"error"},{"inputs":[],"name":"MaxSupplyReached","type":"error"},{"inputs":[],"name":"NotWhitelisted","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"PublicSaleNotActive","type":"error"},{"inputs":[],"name":"QuantityExceedsPublicLimit","type":"error"},{"inputs":[],"name":"WhitelistNotActive","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":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","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":"MINT_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WHITELIST_MINT_LIMIT_PER_ADDRESS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"addAddressToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addrs","type":"address[]"}],"name":"addAddressesToWhitelist","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"batchMint","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"hasWhitelistedMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"isPublicMintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWhitelistActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","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":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicMintLimitPerTx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"removeAddressFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"safeMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxSupply","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setPublicMintLimitPerTx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"newURI","type":"string"}],"name":"setTokenURI","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":[],"name":"togglePublicMint","outputs":[],"stateMutability":"nonpayable","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":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040525f600f5f6101000a81548160ff021916908315150217905550600a60115568015af1d78b58c400006012553480156200003b575f80fd5b5060405162004b7838038062004b78833981810160405281019062000061919062000434565b336040518060400160405280600681526020017f52617a6f727300000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f525a530000000000000000000000000000000000000000000000000000000000815250815f9081620000de9190620006c6565b508060019081620000f09190620006c6565b5050505f600b5f6101000a81548160ff0219169083151502179055505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200017f575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620001769190620007ed565b60405180910390fd5b6200019081620001b260201b60201c565b50816010819055508060139081620001a99190620006c6565b50505062000808565b5f600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600b60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f604051905090565b5f80fd5b5f80fd5b5f819050919050565b6200029c8162000288565b8114620002a7575f80fd5b50565b5f81519050620002ba8162000291565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200031082620002c8565b810181811067ffffffffffffffff82111715620003325762000331620002d8565b5b80604052505050565b5f6200034662000277565b905062000354828262000305565b919050565b5f67ffffffffffffffff821115620003765762000375620002d8565b5b6200038182620002c8565b9050602081019050919050565b5f5b83811015620003ad57808201518184015260208101905062000390565b5f8484015250505050565b5f620003ce620003c88462000359565b6200033b565b905082815260208101848484011115620003ed57620003ec620002c4565b5b620003fa8482856200038e565b509392505050565b5f82601f830112620004195762000418620002c0565b5b81516200042b848260208601620003b8565b91505092915050565b5f80604083850312156200044d576200044c62000280565b5b5f6200045c85828601620002aa565b925050602083015167ffffffffffffffff81111562000480576200047f62000284565b5b6200048e8582860162000402565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680620004e757607f821691505b602082108103620004fd57620004fc620004a2565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620005617fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000524565b6200056d868362000524565b95508019841693508086168417925050509392505050565b5f819050919050565b5f620005ae620005a8620005a28462000288565b62000585565b62000288565b9050919050565b5f819050919050565b620005c9836200058e565b620005e1620005d882620005b5565b84845462000530565b825550505050565b5f90565b620005f7620005e9565b62000604818484620005be565b505050565b5b818110156200062b576200061f5f82620005ed565b6001810190506200060a565b5050565b601f8211156200067a57620006448162000503565b6200064f8462000515565b810160208510156200065f578190505b620006776200066e8562000515565b83018262000609565b50505b505050565b5f82821c905092915050565b5f6200069c5f19846008026200067f565b1980831691505092915050565b5f620006b683836200068b565b9150826002028217905092915050565b620006d18262000498565b67ffffffffffffffff811115620006ed57620006ec620002d8565b5b620006f98254620004cf565b620007068282856200062f565b5f60209050601f8311600181146200073c575f841562000727578287015190505b620007338582620006a9565b865550620007a2565b601f1984166200074c8662000503565b5f5b8281101562000775578489015182556001820191506020850194506020810190506200074e565b8683101562000795578489015162000791601f8916826200068b565b8355505b6001600288020188555050505b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620007d582620007aa565b9050919050565b620007e781620007c9565b82525050565b5f602082019050620008025f830184620007dc565b92915050565b61436280620008165f395ff3fe608060405260043610610266575f3560e01c806355f804b311610143578063a0712d68116100b5578063d5abeb0111610079578063d5abeb01146108e4578063e2ec6ec31461090e578063e4fa4b0614610936578063e985e9c51461095e578063f2fde38b1461099a578063f4a0a528146109c257610266565b8063a0712d6814610812578063a22cb4651461082e578063b88d4fde14610856578063c002d23d1461087e578063c87b56dd146108a857610266565b8063715018a611610107578063715018a6146107405780637b9417c8146107565780637f19d3ec1461077e5780638456cb59146107a85780638da5cb5b146107be57806395d89b41146107e857610266565b806355f804b31461064e5780635c975abb146106765780636352211e146106a05780636f8b44b0146106dc57806370a082311461070457610266565b80633af32abf116101dc57806342842e0e116101a057806342842e0e1461052057806342966c681461054857806343508b051461057057806349c8987d146105ac5780634f6ccce7146105e8578063524513d61461062457610266565b80633af32abf146104665780633ccfd60b146104a25780633f4ba83a146104b85780634047638d146104ce57806340d097c3146104e457610266565b806318160ddd1161022e57806318160ddd1461035c57806323b872dd14610386578063286dd3f5146103ae5780632d6b6224146103d65780632f745c591461040057806330bd8ee11461043c57610266565b806301ffc9a71461026a57806306fdde03146102a6578063081812fc146102d0578063095ea7b31461030c578063162094c414610334575b5f80fd5b348015610275575f80fd5b50610290600480360381019061028b91906132fb565b6109ea565b60405161029d9190613340565b60405180910390f35b3480156102b1575f80fd5b506102ba6109fb565b6040516102c791906133e3565b60405180910390f35b3480156102db575f80fd5b506102f660048036038101906102f19190613436565b610a8a565b60405161030391906134a0565b60405180910390f35b348015610317575f80fd5b50610332600480360381019061032d91906134e3565b610aa5565b005b34801561033f575f80fd5b5061035a6004803603810190610355919061364d565b610abb565b005b348015610367575f80fd5b50610370610b49565b60405161037d91906136b6565b60405180910390f35b348015610391575f80fd5b506103ac60048036038101906103a791906136cf565b610b55565b005b3480156103b9575f80fd5b506103d460048036038101906103cf919061371f565b610c54565b005b3480156103e1575f80fd5b506103ea610cb3565b6040516103f79190613340565b60405180910390f35b34801561040b575f80fd5b50610426600480360381019061042191906134e3565b610cc5565b60405161043391906136b6565b60405180910390f35b348015610447575f80fd5b50610450610d69565b60405161045d91906136b6565b60405180910390f35b348015610471575f80fd5b5061048c6004803603810190610487919061371f565b610d6e565b6040516104999190613340565b60405180910390f35b3480156104ad575f80fd5b506104b6610dc0565b005b3480156104c3575f80fd5b506104cc610ec1565b005b3480156104d9575f80fd5b506104e2610ed3565b005b3480156104ef575f80fd5b5061050a6004803603810190610505919061371f565b610f05565b60405161051791906136b6565b60405180910390f35b34801561052b575f80fd5b50610546600480360381019061054191906136cf565b610fb4565b005b348015610553575f80fd5b5061056e60048036038101906105699190613436565b610fd3565b005b34801561057b575f80fd5b50610596600480360381019061059191906134e3565b610fe9565b6040516105a39190613801565b60405180910390f35b3480156105b7575f80fd5b506105d260048036038101906105cd919061371f565b61113b565b6040516105df9190613340565b60405180910390f35b3480156105f3575f80fd5b5061060e60048036038101906106099190613436565b61118d565b60405161061b91906136b6565b60405180910390f35b34801561062f575f80fd5b506106386111ff565b6040516106459190613340565b60405180910390f35b348015610659575f80fd5b50610674600480360381019061066f9190613821565b611215565b005b348015610681575f80fd5b5061068a611230565b6040516106979190613340565b60405180910390f35b3480156106ab575f80fd5b506106c660048036038101906106c19190613436565b611245565b6040516106d391906134a0565b60405180910390f35b3480156106e7575f80fd5b5061070260048036038101906106fd9190613436565b611256565b005b34801561070f575f80fd5b5061072a6004803603810190610725919061371f565b6112b2565b60405161073791906136b6565b60405180910390f35b34801561074b575f80fd5b50610754611368565b005b348015610761575f80fd5b5061077c6004803603810190610777919061371f565b61137b565b005b348015610789575f80fd5b506107926113db565b60405161079f91906136b6565b60405180910390f35b3480156107b3575f80fd5b506107bc6113e1565b005b3480156107c9575f80fd5b506107d26113f3565b6040516107df91906134a0565b60405180910390f35b3480156107f3575f80fd5b506107fc61141c565b60405161080991906133e3565b60405180910390f35b61082c60048036038101906108279190613436565b6114ac565b005b348015610839575f80fd5b50610854600480360381019061084f9190613892565b611824565b005b348015610861575f80fd5b5061087c6004803603810190610877919061396e565b61183a565b005b348015610889575f80fd5b5061089261185f565b60405161089f91906136b6565b60405180910390f35b3480156108b3575f80fd5b506108ce60048036038101906108c99190613436565b611865565b6040516108db91906133e3565b60405180910390f35b3480156108ef575f80fd5b506108f861193c565b60405161090591906136b6565b60405180910390f35b348015610919575f80fd5b50610934600480360381019061092f9190613a4b565b611942565b005b348015610941575f80fd5b5061095c60048036038101906109579190613436565b6119e5565b005b348015610969575f80fd5b50610984600480360381019061097f9190613a96565b6119f7565b6040516109919190613340565b60405180910390f35b3480156109a5575f80fd5b506109c060048036038101906109bb919061371f565b611a85565b005b3480156109cd575f80fd5b506109e860048036038101906109e39190613436565b611b09565b005b5f6109f482611b1b565b9050919050565b60605f8054610a0990613b01565b80601f0160208091040260200160405190810160405280929190818152602001828054610a3590613b01565b8015610a805780601f10610a5757610100808354040283529160200191610a80565b820191905f5260205f20905b815481529060010190602001808311610a6357829003601f168201915b5050505050905090565b5f610a9482611b7b565b50610a9e82611c01565b9050919050565b610ab78282610ab2611c3a565b611c41565b5050565b610ac3611c53565b5f73ffffffffffffffffffffffffffffffffffffffff16610ae383611cda565b73ffffffffffffffffffffffffffffffffffffffff1603610b3b57816040517f7e273289000000000000000000000000000000000000000000000000000000008152600401610b3291906136b6565b60405180910390fd5b610b458282611d13565b5050565b5f600880549050905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610bc5575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401610bbc91906134a0565b60405180910390fd5b5f610bd88383610bd3611c3a565b611d6d565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c4e578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610c4593929190613b31565b60405180910390fd5b50505050565b610c5c611c53565b5f600d5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b600f5f9054906101000a900460ff1681565b5f610ccf836112b2565b8210610d145782826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610d0b929190613b66565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b600181565b5f600d5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b610dc8611c53565b5f4790505f8111610e0e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0590613bd7565b60405180910390fd5b5f610e176113f3565b73ffffffffffffffffffffffffffffffffffffffff1682604051610e3a90613c22565b5f6040518083038185875af1925050503d805f8114610e74576040519150601f19603f3d011682016040523d82523d5f602084013e610e79565b606091505b5050905080610ebd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb490613c80565b60405180910390fd5b5050565b610ec9611c53565b610ed1611d82565b565b610edb611c53565b600f5f9054906101000a900460ff1615600f5f6101000a81548160ff021916908315150217905550565b5f610f0e611c53565b610f16611230565b15610f4d576040517fab35696f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600c5f815480929190610f6090613ccb565b9190505590506010548110610fa1576040517fd05cb60900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fab8382611de3565b80915050919050565b610fce83838360405180602001604052805f81525061183a565b505050565b610fe55f82610fe0611c3a565b611d6d565b5050565b6060610ff3611c53565b610ffb611230565b15611032576040517fab35696f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6010548261103e610b49565b6110489190613d12565b1115611089576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161108090613d8f565b60405180910390fd5b5f8267ffffffffffffffff8111156110a4576110a3613529565b5b6040519080825280602002602001820160405280156110d25781602001602082028036833780820191505090505b5090505f5b83811015611130575f600c5f8154809291906110f290613ccb565b9190505590506111028682611de3565b8083838151811061111657611115613dad565b5b6020026020010181815250505080806001019150506110d7565b508091505092915050565b5f600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b5f611196610b49565b82106111db575f826040517fa57d13dc0000000000000000000000000000000000000000000000000000000081526004016111d2929190613b66565b60405180910390fd5b600882815481106111ef576111ee613dad565b5b905f5260205f2001549050919050565b5f600f5f9054906101000a900460ff1615905090565b61121d611c53565b806013908161122c9190613f77565b5050565b5f600b5f9054906101000a900460ff16905090565b5f61124f82611b7b565b9050919050565b61125e611c53565b611266610b49565b8110156112a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129f90614090565b60405180910390fd5b8060108190555050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611323575f6040517f89c62b6400000000000000000000000000000000000000000000000000000000815260040161131a91906134a0565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b611370611c53565b6113795f611e00565b565b611383611c53565b6001600d5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b60115481565b6113e9611c53565b6113f1611ec5565b565b5f600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606001805461142b90613b01565b80601f016020809104026020016040519081016040528092919081815260200182805461145790613b01565b80156114a25780601f10611479576101008083540402835291602001916114a2565b820191905f5260205f20905b81548152906001019060200180831161148557829003601f168201915b5050505050905090565b6114b4611230565b156114eb576040517fab35696f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601054816114f7610b49565b6115019190613d12565b1115611539576040517fd05cb60900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115416113f3565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146115bb578060125461158191906140ae565b3410156115ba576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b600f5f9054906101000a900460ff1661176357600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1661164e576040517f584a793800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156116cf576040517f409d64ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114611709576040517f8b3a728000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506117aa565b5f811480611772575060115481115b156117a9576040517f6011666400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5f5b81811015611820575f600c5f8154809291906117c790613ccb565b9190505590506010548110611808576040517fd05cb60900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118123382611de3565b5080806001019150506117ac565b5050565b61183661182f611c3a565b8383611f27565b5050565b611845848484610b55565b611859611850611c3a565b85858585612090565b50505050565b60125481565b60605f73ffffffffffffffffffffffffffffffffffffffff1661188783611cda565b73ffffffffffffffffffffffffffffffffffffffff16036118df57816040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016118d691906136b6565b60405180910390fd5b5f6118e98361223c565b90505f815111156118fd5780915050611937565b5f611906612347565b905080611912856123d7565b604051602001611923929190614173565b604051602081830303815290604052925050505b919050565b60105481565b61194a611c53565b5f5b828290508110156119e0576001600d5f85858581811061196f5761196e613dad565b5b9050602002016020810190611984919061371f565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550808060010191505061194c565b505050565b6119ed611c53565b8060118190555050565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b611a8d611c53565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611afd575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611af491906134a0565b60405180910390fd5b611b0681611e00565b50565b611b11611c53565b8060128190555050565b5f634906490660e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611b745750611b73826124a1565b5b9050919050565b5f80611b8683611cda565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611bf857826040517f7e273289000000000000000000000000000000000000000000000000000000008152600401611bef91906136b6565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b611c4e838383600161251a565b505050565b611c5b611c3a565b73ffffffffffffffffffffffffffffffffffffffff16611c796113f3565b73ffffffffffffffffffffffffffffffffffffffff1614611cd857611c9c611c3a565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611ccf91906134a0565b60405180910390fd5b565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b80600a5f8481526020019081526020015f209081611d319190613f77565b507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce782604051611d6191906136b6565b60405180910390a15050565b5f611d798484846126d9565b90509392505050565b611d8a6126f6565b5f600b5f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611dcc611c3a565b604051611dd991906134a0565b60405180910390a1565b611dfc828260405180602001604052805f815250612736565b5050565b5f600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600b60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b611ecd612759565b6001600b5f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611f10611c3a565b604051611f1d91906134a0565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611f9757816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611f8e91906134a0565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516120839190613340565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115612235578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b81526004016120ee94939291906141f3565b6020604051808303815f875af192505050801561212957506040513d601f19601f820116820180604052508101906121269190614251565b60015b6121aa573d805f8114612157576040519150601f19603f3d011682016040523d82523d5f602084013e61215c565b606091505b505f8151036121a257836040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161219991906134a0565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461223357836040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161222a91906134a0565b60405180910390fd5b505b5050505050565b606061224782611b7b565b505f600a5f8481526020019081526020015f20805461226590613b01565b80601f016020809104026020016040519081016040528092919081815260200182805461229190613b01565b80156122dc5780601f106122b3576101008083540402835291602001916122dc565b820191905f5260205f20905b8154815290600101906020018083116122bf57829003601f168201915b505050505090505f6122ec612347565b90505f815103612300578192505050612342565b5f8251111561233457808260405160200161231c92919061427c565b60405160208183030381529060405292505050612342565b61233d8461279a565b925050505b919050565b60606013805461235690613b01565b80601f016020809104026020016040519081016040528092919081815260200182805461238290613b01565b80156123cd5780601f106123a4576101008083540402835291602001916123cd565b820191905f5260205f20905b8154815290600101906020018083116123b057829003601f168201915b5050505050905090565b60605f60016123e584612800565b0190505f8167ffffffffffffffff81111561240357612402613529565b5b6040519080825280601f01601f1916602001820160405280156124355781602001600182028036833780820191505090505b5090505f82602001820190505b600115612496578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161248b5761248a61429f565b5b0494505f8503612442575b819350505050919050565b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612513575061251282612951565b5b9050919050565b808061255257505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15612684575f61256184611b7b565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156125cb57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156125de57506125dc81846119f7565b155b1561262057826040517fa9fbf51f00000000000000000000000000000000000000000000000000000000815260040161261791906134a0565b60405180910390fd5b811561268257838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b5f6126e2612759565b6126ed848484612a32565b90509392505050565b6126fe611230565b612734576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6127408383612b4c565b61275461274b611c3a565b5f858585612090565b505050565b612761611230565b15612798576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60606127a582611b7b565b505f6127af612347565b90505f8151116127cd5760405180602001604052805f8152506127f8565b806127d7846123d7565b6040516020016127e892919061427c565b6040516020818303038152906040525b915050919050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061285c577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816128525761285161429f565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612899576d04ee2d6d415b85acef8100000000838161288f5761288e61429f565b5b0492506020810190505b662386f26fc1000083106128c857662386f26fc1000083816128be576128bd61429f565b5b0492506010810190505b6305f5e10083106128f1576305f5e10083816128e7576128e661429f565b5b0492506008810190505b612710831061291657612710838161290c5761290b61429f565b5b0492506004810190505b60648310612939576064838161292f5761292e61429f565b5b0492506002810190505b600a8310612948576001810190505b80915050919050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612a1b57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612a2b5750612a2a82612c3f565b5b9050919050565b5f80612a3f858585612ca8565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612a8257612a7d84612eb3565b612ac1565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612ac057612abf8185612ef7565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612b0257612afd84612fce565b612b41565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612b4057612b3f858561308e565b5b5b809150509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612bbc575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612bb391906134a0565b60405180910390fd5b5f612bc883835f611d6d565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612c3a575f6040517f73c6ac6e000000000000000000000000000000000000000000000000000000008152600401612c3191906134a0565b60405180910390fd5b505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f80612cb384611cda565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612cf457612cf3818486613112565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612d7f57612d335f855f8061251a565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612dfe57600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f612f01836112b2565b90505f60075f8481526020019081526020015f205490505f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050828214612fa0575f815f8581526020019081526020015f2054905080825f8581526020019081526020015f20819055508260075f8381526020019081526020015f2081905550505b60075f8581526020019081526020015f205f9055805f8481526020019081526020015f205f90555050505050565b5f6001600880549050612fe191906142cc565b90505f60095f8481526020019081526020015f205490505f6008838154811061300d5761300c613dad565b5b905f5260205f2001549050806008838154811061302d5761302c613dad565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f90556008805480613075576130746142ff565b5b600190038181905f5260205f20015f9055905550505050565b5f600161309a846112b2565b6130a491906142cc565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b61311d8383836131d5565b6131d0575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361319157806040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161318891906136b6565b60405180910390fd5b81816040517f177e802f0000000000000000000000000000000000000000000000000000000081526004016131c7929190613b66565b60405180910390fd5b505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561328c57508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061324d575061324c84846119f7565b5b8061328b57508273ffffffffffffffffffffffffffffffffffffffff1661327383611c01565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6132da816132a6565b81146132e4575f80fd5b50565b5f813590506132f5816132d1565b92915050565b5f602082840312156133105761330f61329e565b5b5f61331d848285016132e7565b91505092915050565b5f8115159050919050565b61333a81613326565b82525050565b5f6020820190506133535f830184613331565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015613390578082015181840152602081019050613375565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6133b582613359565b6133bf8185613363565b93506133cf818560208601613373565b6133d88161339b565b840191505092915050565b5f6020820190508181035f8301526133fb81846133ab565b905092915050565b5f819050919050565b61341581613403565b811461341f575f80fd5b50565b5f813590506134308161340c565b92915050565b5f6020828403121561344b5761344a61329e565b5b5f61345884828501613422565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61348a82613461565b9050919050565b61349a81613480565b82525050565b5f6020820190506134b35f830184613491565b92915050565b6134c281613480565b81146134cc575f80fd5b50565b5f813590506134dd816134b9565b92915050565b5f80604083850312156134f9576134f861329e565b5b5f613506858286016134cf565b925050602061351785828601613422565b9150509250929050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61355f8261339b565b810181811067ffffffffffffffff8211171561357e5761357d613529565b5b80604052505050565b5f613590613295565b905061359c8282613556565b919050565b5f67ffffffffffffffff8211156135bb576135ba613529565b5b6135c48261339b565b9050602081019050919050565b828183375f83830152505050565b5f6135f16135ec846135a1565b613587565b90508281526020810184848401111561360d5761360c613525565b5b6136188482856135d1565b509392505050565b5f82601f83011261363457613633613521565b5b81356136448482602086016135df565b91505092915050565b5f80604083850312156136635761366261329e565b5b5f61367085828601613422565b925050602083013567ffffffffffffffff811115613691576136906132a2565b5b61369d85828601613620565b9150509250929050565b6136b081613403565b82525050565b5f6020820190506136c95f8301846136a7565b92915050565b5f805f606084860312156136e6576136e561329e565b5b5f6136f3868287016134cf565b9350506020613704868287016134cf565b925050604061371586828701613422565b9150509250925092565b5f602082840312156137345761373361329e565b5b5f613741848285016134cf565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61377c81613403565b82525050565b5f61378d8383613773565b60208301905092915050565b5f602082019050919050565b5f6137af8261374a565b6137b98185613754565b93506137c483613764565b805f5b838110156137f45781516137db8882613782565b97506137e683613799565b9250506001810190506137c7565b5085935050505092915050565b5f6020820190508181035f83015261381981846137a5565b905092915050565b5f602082840312156138365761383561329e565b5b5f82013567ffffffffffffffff811115613853576138526132a2565b5b61385f84828501613620565b91505092915050565b61387181613326565b811461387b575f80fd5b50565b5f8135905061388c81613868565b92915050565b5f80604083850312156138a8576138a761329e565b5b5f6138b5858286016134cf565b92505060206138c68582860161387e565b9150509250929050565b5f67ffffffffffffffff8211156138ea576138e9613529565b5b6138f38261339b565b9050602081019050919050565b5f61391261390d846138d0565b613587565b90508281526020810184848401111561392e5761392d613525565b5b6139398482856135d1565b509392505050565b5f82601f83011261395557613954613521565b5b8135613965848260208601613900565b91505092915050565b5f805f80608085870312156139865761398561329e565b5b5f613993878288016134cf565b94505060206139a4878288016134cf565b93505060406139b587828801613422565b925050606085013567ffffffffffffffff8111156139d6576139d56132a2565b5b6139e287828801613941565b91505092959194509250565b5f80fd5b5f80fd5b5f8083601f840112613a0b57613a0a613521565b5b8235905067ffffffffffffffff811115613a2857613a276139ee565b5b602083019150836020820283011115613a4457613a436139f2565b5b9250929050565b5f8060208385031215613a6157613a6061329e565b5b5f83013567ffffffffffffffff811115613a7e57613a7d6132a2565b5b613a8a858286016139f6565b92509250509250929050565b5f8060408385031215613aac57613aab61329e565b5b5f613ab9858286016134cf565b9250506020613aca858286016134cf565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613b1857607f821691505b602082108103613b2b57613b2a613ad4565b5b50919050565b5f606082019050613b445f830186613491565b613b5160208301856136a7565b613b5e6040830184613491565b949350505050565b5f604082019050613b795f830185613491565b613b8660208301846136a7565b9392505050565b7f4e6f2066756e647320746f2077697468647261770000000000000000000000005f82015250565b5f613bc1601483613363565b9150613bcc82613b8d565b602082019050919050565b5f6020820190508181035f830152613bee81613bb5565b9050919050565b5f81905092915050565b50565b5f613c0d5f83613bf5565b9150613c1882613bff565b5f82019050919050565b5f613c2c82613c02565b9150819050919050565b7f5769746864726177616c206661696c65640000000000000000000000000000005f82015250565b5f613c6a601183613363565b9150613c7582613c36565b602082019050919050565b5f6020820190508181035f830152613c9781613c5e565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f613cd582613403565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d0757613d06613c9e565b5b600182019050919050565b5f613d1c82613403565b9150613d2783613403565b9250828201905080821115613d3f57613d3e613c9e565b5b92915050565b7f45786365656473206d617820737570706c7900000000000000000000000000005f82015250565b5f613d79601283613363565b9150613d8482613d45565b602082019050919050565b5f6020820190508181035f830152613da681613d6d565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302613e367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613dfb565b613e408683613dfb565b95508019841693508086168417925050509392505050565b5f819050919050565b5f613e7b613e76613e7184613403565b613e58565b613403565b9050919050565b5f819050919050565b613e9483613e61565b613ea8613ea082613e82565b848454613e07565b825550505050565b5f90565b613ebc613eb0565b613ec7818484613e8b565b505050565b5b81811015613eea57613edf5f82613eb4565b600181019050613ecd565b5050565b601f821115613f2f57613f0081613dda565b613f0984613dec565b81016020851015613f18578190505b613f2c613f2485613dec565b830182613ecc565b50505b505050565b5f82821c905092915050565b5f613f4f5f1984600802613f34565b1980831691505092915050565b5f613f678383613f40565b9150826002028217905092915050565b613f8082613359565b67ffffffffffffffff811115613f9957613f98613529565b5b613fa38254613b01565b613fae828285613eee565b5f60209050601f831160018114613fdf575f8415613fcd578287015190505b613fd78582613f5c565b86555061403e565b601f198416613fed86613dda565b5f5b8281101561401457848901518255600182019150602085019450602081019050613fef565b86831015614031578489015161402d601f891682613f40565b8355505b6001600288020188555050505b505050505050565b7f4e657720737570706c79206c657373207468616e2063757272656e74000000005f82015250565b5f61407a601c83613363565b915061408582614046565b602082019050919050565b5f6020820190508181035f8301526140a78161406e565b9050919050565b5f6140b882613403565b91506140c383613403565b92508282026140d181613403565b915082820484148315176140e8576140e7613c9e565b5b5092915050565b5f81905092915050565b5f61410382613359565b61410d81856140ef565b935061411d818560208601613373565b80840191505092915050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f61415d6005836140ef565b915061416882614129565b600582019050919050565b5f61417e82856140f9565b915061418a82846140f9565b915061419582614151565b91508190509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f6141c5826141a1565b6141cf81856141ab565b93506141df818560208601613373565b6141e88161339b565b840191505092915050565b5f6080820190506142065f830187613491565b6142136020830186613491565b61422060408301856136a7565b818103606083015261423281846141bb565b905095945050505050565b5f8151905061424b816132d1565b92915050565b5f602082840312156142665761426561329e565b5b5f6142738482850161423d565b91505092915050565b5f61428782856140f9565b915061429382846140f9565b91508190509392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6142d682613403565b91506142e183613403565b92508282039050818111156142f9576142f8613c9e565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea2646970667358221220649a70b36c0f950bcf5805f7cb5a393f9f7e7e3b486bf805358a6aad0eb8186f64736f6c6343000816003300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000043697066733a2f2f6261667962656965786d616b736e67366b6e6465373361656b74716967717462726d6c7a7165356a3265737835777a72717775736a73656261626d2f0000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405260043610610266575f3560e01c806355f804b311610143578063a0712d68116100b5578063d5abeb0111610079578063d5abeb01146108e4578063e2ec6ec31461090e578063e4fa4b0614610936578063e985e9c51461095e578063f2fde38b1461099a578063f4a0a528146109c257610266565b8063a0712d6814610812578063a22cb4651461082e578063b88d4fde14610856578063c002d23d1461087e578063c87b56dd146108a857610266565b8063715018a611610107578063715018a6146107405780637b9417c8146107565780637f19d3ec1461077e5780638456cb59146107a85780638da5cb5b146107be57806395d89b41146107e857610266565b806355f804b31461064e5780635c975abb146106765780636352211e146106a05780636f8b44b0146106dc57806370a082311461070457610266565b80633af32abf116101dc57806342842e0e116101a057806342842e0e1461052057806342966c681461054857806343508b051461057057806349c8987d146105ac5780634f6ccce7146105e8578063524513d61461062457610266565b80633af32abf146104665780633ccfd60b146104a25780633f4ba83a146104b85780634047638d146104ce57806340d097c3146104e457610266565b806318160ddd1161022e57806318160ddd1461035c57806323b872dd14610386578063286dd3f5146103ae5780632d6b6224146103d65780632f745c591461040057806330bd8ee11461043c57610266565b806301ffc9a71461026a57806306fdde03146102a6578063081812fc146102d0578063095ea7b31461030c578063162094c414610334575b5f80fd5b348015610275575f80fd5b50610290600480360381019061028b91906132fb565b6109ea565b60405161029d9190613340565b60405180910390f35b3480156102b1575f80fd5b506102ba6109fb565b6040516102c791906133e3565b60405180910390f35b3480156102db575f80fd5b506102f660048036038101906102f19190613436565b610a8a565b60405161030391906134a0565b60405180910390f35b348015610317575f80fd5b50610332600480360381019061032d91906134e3565b610aa5565b005b34801561033f575f80fd5b5061035a6004803603810190610355919061364d565b610abb565b005b348015610367575f80fd5b50610370610b49565b60405161037d91906136b6565b60405180910390f35b348015610391575f80fd5b506103ac60048036038101906103a791906136cf565b610b55565b005b3480156103b9575f80fd5b506103d460048036038101906103cf919061371f565b610c54565b005b3480156103e1575f80fd5b506103ea610cb3565b6040516103f79190613340565b60405180910390f35b34801561040b575f80fd5b50610426600480360381019061042191906134e3565b610cc5565b60405161043391906136b6565b60405180910390f35b348015610447575f80fd5b50610450610d69565b60405161045d91906136b6565b60405180910390f35b348015610471575f80fd5b5061048c6004803603810190610487919061371f565b610d6e565b6040516104999190613340565b60405180910390f35b3480156104ad575f80fd5b506104b6610dc0565b005b3480156104c3575f80fd5b506104cc610ec1565b005b3480156104d9575f80fd5b506104e2610ed3565b005b3480156104ef575f80fd5b5061050a6004803603810190610505919061371f565b610f05565b60405161051791906136b6565b60405180910390f35b34801561052b575f80fd5b50610546600480360381019061054191906136cf565b610fb4565b005b348015610553575f80fd5b5061056e60048036038101906105699190613436565b610fd3565b005b34801561057b575f80fd5b50610596600480360381019061059191906134e3565b610fe9565b6040516105a39190613801565b60405180910390f35b3480156105b7575f80fd5b506105d260048036038101906105cd919061371f565b61113b565b6040516105df9190613340565b60405180910390f35b3480156105f3575f80fd5b5061060e60048036038101906106099190613436565b61118d565b60405161061b91906136b6565b60405180910390f35b34801561062f575f80fd5b506106386111ff565b6040516106459190613340565b60405180910390f35b348015610659575f80fd5b50610674600480360381019061066f9190613821565b611215565b005b348015610681575f80fd5b5061068a611230565b6040516106979190613340565b60405180910390f35b3480156106ab575f80fd5b506106c660048036038101906106c19190613436565b611245565b6040516106d391906134a0565b60405180910390f35b3480156106e7575f80fd5b5061070260048036038101906106fd9190613436565b611256565b005b34801561070f575f80fd5b5061072a6004803603810190610725919061371f565b6112b2565b60405161073791906136b6565b60405180910390f35b34801561074b575f80fd5b50610754611368565b005b348015610761575f80fd5b5061077c6004803603810190610777919061371f565b61137b565b005b348015610789575f80fd5b506107926113db565b60405161079f91906136b6565b60405180910390f35b3480156107b3575f80fd5b506107bc6113e1565b005b3480156107c9575f80fd5b506107d26113f3565b6040516107df91906134a0565b60405180910390f35b3480156107f3575f80fd5b506107fc61141c565b60405161080991906133e3565b60405180910390f35b61082c60048036038101906108279190613436565b6114ac565b005b348015610839575f80fd5b50610854600480360381019061084f9190613892565b611824565b005b348015610861575f80fd5b5061087c6004803603810190610877919061396e565b61183a565b005b348015610889575f80fd5b5061089261185f565b60405161089f91906136b6565b60405180910390f35b3480156108b3575f80fd5b506108ce60048036038101906108c99190613436565b611865565b6040516108db91906133e3565b60405180910390f35b3480156108ef575f80fd5b506108f861193c565b60405161090591906136b6565b60405180910390f35b348015610919575f80fd5b50610934600480360381019061092f9190613a4b565b611942565b005b348015610941575f80fd5b5061095c60048036038101906109579190613436565b6119e5565b005b348015610969575f80fd5b50610984600480360381019061097f9190613a96565b6119f7565b6040516109919190613340565b60405180910390f35b3480156109a5575f80fd5b506109c060048036038101906109bb919061371f565b611a85565b005b3480156109cd575f80fd5b506109e860048036038101906109e39190613436565b611b09565b005b5f6109f482611b1b565b9050919050565b60605f8054610a0990613b01565b80601f0160208091040260200160405190810160405280929190818152602001828054610a3590613b01565b8015610a805780601f10610a5757610100808354040283529160200191610a80565b820191905f5260205f20905b815481529060010190602001808311610a6357829003601f168201915b5050505050905090565b5f610a9482611b7b565b50610a9e82611c01565b9050919050565b610ab78282610ab2611c3a565b611c41565b5050565b610ac3611c53565b5f73ffffffffffffffffffffffffffffffffffffffff16610ae383611cda565b73ffffffffffffffffffffffffffffffffffffffff1603610b3b57816040517f7e273289000000000000000000000000000000000000000000000000000000008152600401610b3291906136b6565b60405180910390fd5b610b458282611d13565b5050565b5f600880549050905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610bc5575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401610bbc91906134a0565b60405180910390fd5b5f610bd88383610bd3611c3a565b611d6d565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c4e578382826040517f64283d7b000000000000000000000000000000000000000000000000000000008152600401610c4593929190613b31565b60405180910390fd5b50505050565b610c5c611c53565b5f600d5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b600f5f9054906101000a900460ff1681565b5f610ccf836112b2565b8210610d145782826040517fa57d13dc000000000000000000000000000000000000000000000000000000008152600401610d0b929190613b66565b60405180910390fd5b60065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b600181565b5f600d5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b610dc8611c53565b5f4790505f8111610e0e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0590613bd7565b60405180910390fd5b5f610e176113f3565b73ffffffffffffffffffffffffffffffffffffffff1682604051610e3a90613c22565b5f6040518083038185875af1925050503d805f8114610e74576040519150601f19603f3d011682016040523d82523d5f602084013e610e79565b606091505b5050905080610ebd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb490613c80565b60405180910390fd5b5050565b610ec9611c53565b610ed1611d82565b565b610edb611c53565b600f5f9054906101000a900460ff1615600f5f6101000a81548160ff021916908315150217905550565b5f610f0e611c53565b610f16611230565b15610f4d576040517fab35696f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600c5f815480929190610f6090613ccb565b9190505590506010548110610fa1576040517fd05cb60900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fab8382611de3565b80915050919050565b610fce83838360405180602001604052805f81525061183a565b505050565b610fe55f82610fe0611c3a565b611d6d565b5050565b6060610ff3611c53565b610ffb611230565b15611032576040517fab35696f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6010548261103e610b49565b6110489190613d12565b1115611089576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161108090613d8f565b60405180910390fd5b5f8267ffffffffffffffff8111156110a4576110a3613529565b5b6040519080825280602002602001820160405280156110d25781602001602082028036833780820191505090505b5090505f5b83811015611130575f600c5f8154809291906110f290613ccb565b9190505590506111028682611de3565b8083838151811061111657611115613dad565b5b6020026020010181815250505080806001019150506110d7565b508091505092915050565b5f600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b5f611196610b49565b82106111db575f826040517fa57d13dc0000000000000000000000000000000000000000000000000000000081526004016111d2929190613b66565b60405180910390fd5b600882815481106111ef576111ee613dad565b5b905f5260205f2001549050919050565b5f600f5f9054906101000a900460ff1615905090565b61121d611c53565b806013908161122c9190613f77565b5050565b5f600b5f9054906101000a900460ff16905090565b5f61124f82611b7b565b9050919050565b61125e611c53565b611266610b49565b8110156112a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129f90614090565b60405180910390fd5b8060108190555050565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611323575f6040517f89c62b6400000000000000000000000000000000000000000000000000000000815260040161131a91906134a0565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b611370611c53565b6113795f611e00565b565b611383611c53565b6001600d5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b60115481565b6113e9611c53565b6113f1611ec5565b565b5f600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606001805461142b90613b01565b80601f016020809104026020016040519081016040528092919081815260200182805461145790613b01565b80156114a25780601f10611479576101008083540402835291602001916114a2565b820191905f5260205f20905b81548152906001019060200180831161148557829003601f168201915b5050505050905090565b6114b4611230565b156114eb576040517fab35696f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601054816114f7610b49565b6115019190613d12565b1115611539576040517fd05cb60900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115416113f3565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146115bb578060125461158191906140ae565b3410156115ba576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b600f5f9054906101000a900460ff1661176357600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1661164e576040517f584a793800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16156116cf576040517f409d64ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018114611709576040517f8b3a728000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506117aa565b5f811480611772575060115481115b156117a9576040517f6011666400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b5f5b81811015611820575f600c5f8154809291906117c790613ccb565b9190505590506010548110611808576040517fd05cb60900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118123382611de3565b5080806001019150506117ac565b5050565b61183661182f611c3a565b8383611f27565b5050565b611845848484610b55565b611859611850611c3a565b85858585612090565b50505050565b60125481565b60605f73ffffffffffffffffffffffffffffffffffffffff1661188783611cda565b73ffffffffffffffffffffffffffffffffffffffff16036118df57816040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016118d691906136b6565b60405180910390fd5b5f6118e98361223c565b90505f815111156118fd5780915050611937565b5f611906612347565b905080611912856123d7565b604051602001611923929190614173565b604051602081830303815290604052925050505b919050565b60105481565b61194a611c53565b5f5b828290508110156119e0576001600d5f85858581811061196f5761196e613dad565b5b9050602002016020810190611984919061371f565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550808060010191505061194c565b505050565b6119ed611c53565b8060118190555050565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b611a8d611c53565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611afd575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611af491906134a0565b60405180910390fd5b611b0681611e00565b50565b611b11611c53565b8060128190555050565b5f634906490660e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611b745750611b73826124a1565b5b9050919050565b5f80611b8683611cda565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611bf857826040517f7e273289000000000000000000000000000000000000000000000000000000008152600401611bef91906136b6565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b611c4e838383600161251a565b505050565b611c5b611c3a565b73ffffffffffffffffffffffffffffffffffffffff16611c796113f3565b73ffffffffffffffffffffffffffffffffffffffff1614611cd857611c9c611c3a565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611ccf91906134a0565b60405180910390fd5b565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b80600a5f8481526020019081526020015f209081611d319190613f77565b507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce782604051611d6191906136b6565b60405180910390a15050565b5f611d798484846126d9565b90509392505050565b611d8a6126f6565b5f600b5f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611dcc611c3a565b604051611dd991906134a0565b60405180910390a1565b611dfc828260405180602001604052805f815250612736565b5050565b5f600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600b60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b611ecd612759565b6001600b5f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611f10611c3a565b604051611f1d91906134a0565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611f9757816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611f8e91906134a0565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516120839190613340565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115612235578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02868685856040518563ffffffff1660e01b81526004016120ee94939291906141f3565b6020604051808303815f875af192505050801561212957506040513d601f19601f820116820180604052508101906121269190614251565b60015b6121aa573d805f8114612157576040519150601f19603f3d011682016040523d82523d5f602084013e61215c565b606091505b505f8151036121a257836040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161219991906134a0565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461223357836040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161222a91906134a0565b60405180910390fd5b505b5050505050565b606061224782611b7b565b505f600a5f8481526020019081526020015f20805461226590613b01565b80601f016020809104026020016040519081016040528092919081815260200182805461229190613b01565b80156122dc5780601f106122b3576101008083540402835291602001916122dc565b820191905f5260205f20905b8154815290600101906020018083116122bf57829003601f168201915b505050505090505f6122ec612347565b90505f815103612300578192505050612342565b5f8251111561233457808260405160200161231c92919061427c565b60405160208183030381529060405292505050612342565b61233d8461279a565b925050505b919050565b60606013805461235690613b01565b80601f016020809104026020016040519081016040528092919081815260200182805461238290613b01565b80156123cd5780601f106123a4576101008083540402835291602001916123cd565b820191905f5260205f20905b8154815290600101906020018083116123b057829003601f168201915b5050505050905090565b60605f60016123e584612800565b0190505f8167ffffffffffffffff81111561240357612402613529565b5b6040519080825280601f01601f1916602001820160405280156124355781602001600182028036833780820191505090505b5090505f82602001820190505b600115612496578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161248b5761248a61429f565b5b0494505f8503612442575b819350505050919050565b5f7f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612513575061251282612951565b5b9050919050565b808061255257505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15612684575f61256184611b7b565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156125cb57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156125de57506125dc81846119f7565b155b1561262057826040517fa9fbf51f00000000000000000000000000000000000000000000000000000000815260040161261791906134a0565b60405180910390fd5b811561268257838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b5f6126e2612759565b6126ed848484612a32565b90509392505050565b6126fe611230565b612734576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6127408383612b4c565b61275461274b611c3a565b5f858585612090565b505050565b612761611230565b15612798576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60606127a582611b7b565b505f6127af612347565b90505f8151116127cd5760405180602001604052805f8152506127f8565b806127d7846123d7565b6040516020016127e892919061427c565b6040516020818303038152906040525b915050919050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061285c577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816128525761285161429f565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612899576d04ee2d6d415b85acef8100000000838161288f5761288e61429f565b5b0492506020810190505b662386f26fc1000083106128c857662386f26fc1000083816128be576128bd61429f565b5b0492506010810190505b6305f5e10083106128f1576305f5e10083816128e7576128e661429f565b5b0492506008810190505b612710831061291657612710838161290c5761290b61429f565b5b0492506004810190505b60648310612939576064838161292f5761292e61429f565b5b0492506002810190505b600a8310612948576001810190505b80915050919050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612a1b57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612a2b5750612a2a82612c3f565b5b9050919050565b5f80612a3f858585612ca8565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612a8257612a7d84612eb3565b612ac1565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612ac057612abf8185612ef7565b5b5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612b0257612afd84612fce565b612b41565b8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612b4057612b3f858561308e565b5b5b809150509392505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612bbc575f6040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401612bb391906134a0565b60405180910390fd5b5f612bc883835f611d6d565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612c3a575f6040517f73c6ac6e000000000000000000000000000000000000000000000000000000008152600401612c3191906134a0565b60405180910390fd5b505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f80612cb384611cda565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612cf457612cf3818486613112565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612d7f57612d335f855f8061251a565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612dfe57600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b60088054905060095f8381526020019081526020015f2081905550600881908060018154018082558091505060019003905f5260205f20015f909190919091505550565b5f612f01836112b2565b90505f60075f8481526020019081526020015f205490505f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050828214612fa0575f815f8581526020019081526020015f2054905080825f8581526020019081526020015f20819055508260075f8381526020019081526020015f2081905550505b60075f8581526020019081526020015f205f9055805f8481526020019081526020015f205f90555050505050565b5f6001600880549050612fe191906142cc565b90505f60095f8481526020019081526020015f205490505f6008838154811061300d5761300c613dad565b5b905f5260205f2001549050806008838154811061302d5761302c613dad565b5b905f5260205f2001819055508160095f8381526020019081526020015f208190555060095f8581526020019081526020015f205f90556008805480613075576130746142ff565b5b600190038181905f5260205f20015f9055905550505050565b5f600161309a846112b2565b6130a491906142cc565b90508160065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055508060075f8481526020019081526020015f2081905550505050565b61311d8383836131d5565b6131d0575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361319157806040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161318891906136b6565b60405180910390fd5b81816040517f177e802f0000000000000000000000000000000000000000000000000000000081526004016131c7929190613b66565b60405180910390fd5b505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561328c57508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061324d575061324c84846119f7565b5b8061328b57508273ffffffffffffffffffffffffffffffffffffffff1661327383611c01565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6132da816132a6565b81146132e4575f80fd5b50565b5f813590506132f5816132d1565b92915050565b5f602082840312156133105761330f61329e565b5b5f61331d848285016132e7565b91505092915050565b5f8115159050919050565b61333a81613326565b82525050565b5f6020820190506133535f830184613331565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015613390578082015181840152602081019050613375565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6133b582613359565b6133bf8185613363565b93506133cf818560208601613373565b6133d88161339b565b840191505092915050565b5f6020820190508181035f8301526133fb81846133ab565b905092915050565b5f819050919050565b61341581613403565b811461341f575f80fd5b50565b5f813590506134308161340c565b92915050565b5f6020828403121561344b5761344a61329e565b5b5f61345884828501613422565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61348a82613461565b9050919050565b61349a81613480565b82525050565b5f6020820190506134b35f830184613491565b92915050565b6134c281613480565b81146134cc575f80fd5b50565b5f813590506134dd816134b9565b92915050565b5f80604083850312156134f9576134f861329e565b5b5f613506858286016134cf565b925050602061351785828601613422565b9150509250929050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61355f8261339b565b810181811067ffffffffffffffff8211171561357e5761357d613529565b5b80604052505050565b5f613590613295565b905061359c8282613556565b919050565b5f67ffffffffffffffff8211156135bb576135ba613529565b5b6135c48261339b565b9050602081019050919050565b828183375f83830152505050565b5f6135f16135ec846135a1565b613587565b90508281526020810184848401111561360d5761360c613525565b5b6136188482856135d1565b509392505050565b5f82601f83011261363457613633613521565b5b81356136448482602086016135df565b91505092915050565b5f80604083850312156136635761366261329e565b5b5f61367085828601613422565b925050602083013567ffffffffffffffff811115613691576136906132a2565b5b61369d85828601613620565b9150509250929050565b6136b081613403565b82525050565b5f6020820190506136c95f8301846136a7565b92915050565b5f805f606084860312156136e6576136e561329e565b5b5f6136f3868287016134cf565b9350506020613704868287016134cf565b925050604061371586828701613422565b9150509250925092565b5f602082840312156137345761373361329e565b5b5f613741848285016134cf565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61377c81613403565b82525050565b5f61378d8383613773565b60208301905092915050565b5f602082019050919050565b5f6137af8261374a565b6137b98185613754565b93506137c483613764565b805f5b838110156137f45781516137db8882613782565b97506137e683613799565b9250506001810190506137c7565b5085935050505092915050565b5f6020820190508181035f83015261381981846137a5565b905092915050565b5f602082840312156138365761383561329e565b5b5f82013567ffffffffffffffff811115613853576138526132a2565b5b61385f84828501613620565b91505092915050565b61387181613326565b811461387b575f80fd5b50565b5f8135905061388c81613868565b92915050565b5f80604083850312156138a8576138a761329e565b5b5f6138b5858286016134cf565b92505060206138c68582860161387e565b9150509250929050565b5f67ffffffffffffffff8211156138ea576138e9613529565b5b6138f38261339b565b9050602081019050919050565b5f61391261390d846138d0565b613587565b90508281526020810184848401111561392e5761392d613525565b5b6139398482856135d1565b509392505050565b5f82601f83011261395557613954613521565b5b8135613965848260208601613900565b91505092915050565b5f805f80608085870312156139865761398561329e565b5b5f613993878288016134cf565b94505060206139a4878288016134cf565b93505060406139b587828801613422565b925050606085013567ffffffffffffffff8111156139d6576139d56132a2565b5b6139e287828801613941565b91505092959194509250565b5f80fd5b5f80fd5b5f8083601f840112613a0b57613a0a613521565b5b8235905067ffffffffffffffff811115613a2857613a276139ee565b5b602083019150836020820283011115613a4457613a436139f2565b5b9250929050565b5f8060208385031215613a6157613a6061329e565b5b5f83013567ffffffffffffffff811115613a7e57613a7d6132a2565b5b613a8a858286016139f6565b92509250509250929050565b5f8060408385031215613aac57613aab61329e565b5b5f613ab9858286016134cf565b9250506020613aca858286016134cf565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613b1857607f821691505b602082108103613b2b57613b2a613ad4565b5b50919050565b5f606082019050613b445f830186613491565b613b5160208301856136a7565b613b5e6040830184613491565b949350505050565b5f604082019050613b795f830185613491565b613b8660208301846136a7565b9392505050565b7f4e6f2066756e647320746f2077697468647261770000000000000000000000005f82015250565b5f613bc1601483613363565b9150613bcc82613b8d565b602082019050919050565b5f6020820190508181035f830152613bee81613bb5565b9050919050565b5f81905092915050565b50565b5f613c0d5f83613bf5565b9150613c1882613bff565b5f82019050919050565b5f613c2c82613c02565b9150819050919050565b7f5769746864726177616c206661696c65640000000000000000000000000000005f82015250565b5f613c6a601183613363565b9150613c7582613c36565b602082019050919050565b5f6020820190508181035f830152613c9781613c5e565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f613cd582613403565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d0757613d06613c9e565b5b600182019050919050565b5f613d1c82613403565b9150613d2783613403565b9250828201905080821115613d3f57613d3e613c9e565b5b92915050565b7f45786365656473206d617820737570706c7900000000000000000000000000005f82015250565b5f613d79601283613363565b9150613d8482613d45565b602082019050919050565b5f6020820190508181035f830152613da681613d6d565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302613e367fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613dfb565b613e408683613dfb565b95508019841693508086168417925050509392505050565b5f819050919050565b5f613e7b613e76613e7184613403565b613e58565b613403565b9050919050565b5f819050919050565b613e9483613e61565b613ea8613ea082613e82565b848454613e07565b825550505050565b5f90565b613ebc613eb0565b613ec7818484613e8b565b505050565b5b81811015613eea57613edf5f82613eb4565b600181019050613ecd565b5050565b601f821115613f2f57613f0081613dda565b613f0984613dec565b81016020851015613f18578190505b613f2c613f2485613dec565b830182613ecc565b50505b505050565b5f82821c905092915050565b5f613f4f5f1984600802613f34565b1980831691505092915050565b5f613f678383613f40565b9150826002028217905092915050565b613f8082613359565b67ffffffffffffffff811115613f9957613f98613529565b5b613fa38254613b01565b613fae828285613eee565b5f60209050601f831160018114613fdf575f8415613fcd578287015190505b613fd78582613f5c565b86555061403e565b601f198416613fed86613dda565b5f5b8281101561401457848901518255600182019150602085019450602081019050613fef565b86831015614031578489015161402d601f891682613f40565b8355505b6001600288020188555050505b505050505050565b7f4e657720737570706c79206c657373207468616e2063757272656e74000000005f82015250565b5f61407a601c83613363565b915061408582614046565b602082019050919050565b5f6020820190508181035f8301526140a78161406e565b9050919050565b5f6140b882613403565b91506140c383613403565b92508282026140d181613403565b915082820484148315176140e8576140e7613c9e565b5b5092915050565b5f81905092915050565b5f61410382613359565b61410d81856140ef565b935061411d818560208601613373565b80840191505092915050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f61415d6005836140ef565b915061416882614129565b600582019050919050565b5f61417e82856140f9565b915061418a82846140f9565b915061419582614151565b91508190509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f6141c5826141a1565b6141cf81856141ab565b93506141df818560208601613373565b6141e88161339b565b840191505092915050565b5f6080820190506142065f830187613491565b6142136020830186613491565b61422060408301856136a7565b818103606083015261423281846141bb565b905095945050505050565b5f8151905061424b816132d1565b92915050565b5f602082840312156142665761426561329e565b5b5f6142738482850161423d565b91505092915050565b5f61428782856140f9565b915061429382846140f9565b91508190509392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6142d682613403565b91506142e183613403565b92508282039050818111156142f9576142f8613c9e565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffdfea2646970667358221220649a70b36c0f950bcf5805f7cb5a393f9f7e7e3b486bf805358a6aad0eb8186f64736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000043697066733a2f2f6261667962656965786d616b736e67366b6e6465373361656b74716967717462726d6c7a7165356a3265737835777a72717775736a73656261626d2f0000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _maxSupply (uint256): 500
Arg [1] : initialBaseURI (string): ipfs://bafybeiexmaksng6knde73aektqigqtbrmlzqe5j2esx5wzrqwusjsebabm/
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000043
Arg [3] : 697066733a2f2f6261667962656965786d616b736e67366b6e6465373361656b
Arg [4] : 74716967717462726d6c7a7165356a3265737835777a72717775736a73656261
Arg [5] : 626d2f0000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
147331:11028:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;157912:246;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110080:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;111252:158;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;111071:115;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;149927:276;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;128510:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;111921:588;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;150311:249;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;147801:38;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;128174:260;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;148036:60;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;155797:110;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151477:271;;;;;;;;;;;;;:::i;:::-;;158291:65;;;;;;;;;;;;;:::i;:::-;;150683:104;;;;;;;;;;;;;:::i;:::-;;154365:402;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;112580:134;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;125098:318;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;155009:570;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156132:124;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;128691:231;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156386:101;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156644:108;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;135851:86;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;109893:120;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;150939:179;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;109618:213;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;143706:103;;;;;;;;;;;;;:::i;:::-;;149161:108;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;147937:40;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;158222:61;;;;;;;;;;;;;:::i;:::-;;143031:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110240:95;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151965:2090;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111482:146;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;112785:236;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;148134:36;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;156760:612;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;147880:24;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;149557:208;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;151295:112;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;111699:155;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;143964:220;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;148948:101;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;157912:246;158085:4;158114:36;158138:11;158114:23;:36::i;:::-;158107:43;;157912:246;;;:::o;110080:91::-;110125:13;110158:5;110151:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110080:91;:::o;111252:158::-;111319:7;111339:22;111353:7;111339:13;:22::i;:::-;;111381:21;111394:7;111381:12;:21::i;:::-;111374:28;;111252:158;;;:::o;111071:115::-;111143:35;111152:2;111156:7;111165:12;:10;:12::i;:::-;111143:8;:35::i;:::-;111071:115;;:::o;149927:276::-;142917:13;:11;:13::i;:::-;150073:1:::1;150044:31;;:17;150053:7;150044:8;:17::i;:::-;:31;;::::0;150040:116:::1;;150136:7;150099:45;;;;;;;;;;;:::i;:::-;;;;;;;;150040:116;150166:29;150179:7;150188:6;150166:12;:29::i;:::-;149927:276:::0;;:::o;128510:104::-;128562:7;128589:10;:17;;;;128582:24;;128510:104;:::o;111921:588::-;112030:1;112016:16;;:2;:16;;;112012:89;;112086:1;112056:33;;;;;;;;;;;:::i;:::-;;;;;;;;112012:89;112322:21;112346:34;112354:2;112358:7;112367:12;:10;:12::i;:::-;112346:7;:34::i;:::-;112322:58;;112412:4;112395:21;;:13;:21;;;112391:111;;112461:4;112467:7;112476:13;112440:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;112391:111;112001:508;111921:588;;;:::o;150311:249::-;142917:13;:11;:13::i;:::-;150412:5:::1;150389:14;:20;150404:4;150389:20;;;;;;;;;;;;;;;;:28;;;;;;;;;;;;;;;;;;150311:249:::0;:::o;147801:38::-;;;;;;;;;;;;;:::o;128174:260::-;128262:7;128295:16;128305:5;128295:9;:16::i;:::-;128286:5;:25;128282:101;;128358:5;128365;128335:36;;;;;;;;;;;;:::i;:::-;;;;;;;;128282:101;128400:12;:19;128413:5;128400:19;;;;;;;;;;;;;;;:26;128420:5;128400:26;;;;;;;;;;;;128393:33;;128174:260;;;;:::o;148036:60::-;148095:1;148036:60;:::o;155797:110::-;155855:4;155879:14;:20;155894:4;155879:20;;;;;;;;;;;;;;;;;;;;;;;;;155872:27;;155797:110;;;:::o;151477:271::-;142917:13;:11;:13::i;:::-;151525:15:::1;151543:21;151525:39;;151593:1;151583:7;:11;151575:44;;;;;;;;;;;;:::i;:::-;;;;;;;;;151633:12;151659:7;:5;:7::i;:::-;151651:21;;151680:7;151651:41;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;151632:60;;;151711:7;151703:37;;;;;;;;;;;;:::i;:::-;;;;;;;;;151514:234;;151477:271::o:0;158291:65::-;142917:13;:11;:13::i;:::-;158338:10:::1;:8;:10::i;:::-;158291:65::o:0;150683:104::-;142917:13;:11;:13::i;:::-;150761:18:::1;;;;;;;;;;;150760:19;150739:18;;:40;;;;;;;;;;;;;;;;;;150683:104::o:0;154365:402::-;154421:7;142917:13;:11;:13::i;:::-;154485:8:::1;:6;:8::i;:::-;154481:37;;;154502:16;;;;;;;;;;;;;;154481:37;154531:15;154549:12;;:14;;;;;;;;;:::i;:::-;;;;;154531:32;;154589:9;;154578:7;:20;154574:51;;154607:18;;;;;;;;;;;;;;154574:51;154638:22;154648:2;154652:7;154638:9;:22::i;:::-;154752:7;154745:14;;;154365:402:::0;;;:::o;112580:134::-;112667:39;112684:4;112690:2;112694:7;112667:39;;;;;;;;;;;;:16;:39::i;:::-;112580:134;;;:::o;125098:318::-;125366:42;125382:1;125386:7;125395:12;:10;:12::i;:::-;125366:7;:42::i;:::-;;125098:318;:::o;155009:570::-;155109:16;142917:13;:11;:13::i;:::-;155182:8:::1;:6;:8::i;:::-;155178:37;;;155199:16;;;;;;;;;;;;;;155178:37;155264:9;;155252:8;155236:13;:11;:13::i;:::-;:24;;;;:::i;:::-;:37;;155228:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;155309:25;155351:8;155337:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;155309:51;;155378:9;155373:171;155397:8;155393:1;:12;155373:171;;;155427:15;155445:12;;:14;;;;;;;;;:::i;:::-;;;;;155427:32;;155474:22;155484:2;155488:7;155474:9;:22::i;:::-;155525:7;155511:8;155520:1;155511:11;;;;;;;;:::i;:::-;;;;;;;:21;;;::::0;::::1;155412:132;155407:3;;;;;;;155373:171;;;;155563:8;155556:15;;;155009:570:::0;;;;:::o;156132:124::-;156197:4;156221:21;:27;156243:4;156221:27;;;;;;;;;;;;;;;;;;;;;;;;;156214:34;;156132:124;;;:::o;128691:231::-;128757:7;128790:13;:11;:13::i;:::-;128781:5;:22;128777:103;;128858:1;128862:5;128827:41;;;;;;;;;;;;:::i;:::-;;;;;;;;128777:103;128897:10;128908:5;128897:17;;;;;;;;:::i;:::-;;;;;;;;;;128890:24;;128691:231;;;:::o;156386:101::-;156436:4;156461:18;;;;;;;;;;;156460:19;156453:26;;156386:101;:::o;156644:108::-;142917:13;:11;:13::i;:::-;156734:10:::1;156718:13;:26;;;;;;:::i;:::-;;156644:108:::0;:::o;135851:86::-;135898:4;135922:7;;;;;;;;;;;135915:14;;135851:86;:::o;109893:120::-;109956:7;109983:22;109997:7;109983:13;:22::i;:::-;109976:29;;109893:120;;;:::o;150939:179::-;142917:13;:11;:13::i;:::-;151031::::1;:11;:13::i;:::-;151017:10;:27;;151009:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;151100:10;151088:9;:22;;;;150939:179:::0;:::o;109618:213::-;109681:7;109722:1;109705:19;;:5;:19;;;109701:89;;109775:1;109748:30;;;;;;;;;;;:::i;:::-;;;;;;;;109701:89;109807:9;:16;109817:5;109807:16;;;;;;;;;;;;;;;;109800:23;;109618:213;;;:::o;143706:103::-;142917:13;:11;:13::i;:::-;143771:30:::1;143798:1;143771:18;:30::i;:::-;143706:103::o:0;149161:108::-;142917:13;:11;:13::i;:::-;149257:4:::1;149234:14;:20;149249:4;149234:20;;;;;;;;;;;;;;;;:27;;;;;;;;;;;;;;;;;;149161:108:::0;:::o;147937:40::-;;;;:::o;158222:61::-;142917:13;:11;:13::i;:::-;158267:8:::1;:6;:8::i;:::-;158222:61::o:0;143031:87::-;143077:7;143104:6;;;;;;;;;;;143097:13;;143031:87;:::o;110240:95::-;110287:13;110320:7;110313:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110240:95;:::o;151965:2090::-;152067:8;:6;:8::i;:::-;152063:37;;;152084:16;;;;;;;;;;;;;;152063:37;152181:9;;152170:8;152154:13;:11;:13::i;:::-;:24;;;;:::i;:::-;:36;152150:94;;;152214:18;;;;;;;;;;;;;;152150:94;152323:7;:5;:7::i;:::-;152309:21;;:10;:21;;;152305:155;;152376:8;152363:10;;:21;;;;:::i;:::-;152351:9;:33;152347:102;;;152412:21;;;;;;;;;;;;;;152347:102;152305:155;152519:18;;;;;;;;;;;152514:992;;152606:14;:26;152621:10;152606:26;;;;;;;;;;;;;;;;;;;;;;;;;152601:91;;152660:16;;;;;;;;;;;;;;152601:91;152776:21;:33;152798:10;152776:33;;;;;;;;;;;;;;;;;;;;;;;;;152772:107;;;152837:26;;;;;;;;;;;;;;152772:107;148095:1;152957:8;:44;152953:113;;153029:21;;;;;;;;;;;;;;152953:113;153181:4;153145:21;:33;153167:10;153145:33;;;;;;;;;;;;;;;;:40;;;;;;;;;;;;;;;;;;152514:992;;;153334:1;153322:8;:13;:48;;;;153350:20;;153339:8;:31;153322:48;153318:124;;;153398:28;;;;;;;;;;;;;;153318:124;152514:992;153559:9;153554:494;153578:8;153574:1;:12;153554:494;;;153608:15;153626:12;;:14;;;;;;;;;:::i;:::-;;;;;153608:32;;153734:9;;153723:7;:20;153719:176;;153861:18;;;;;;;;;;;;;;153719:176;153911:30;153921:10;153933:7;153911:9;:30::i;:::-;153593:455;153588:3;;;;;;;153554:494;;;;151965:2090;:::o;111482:146::-;111568:52;111587:12;:10;:12::i;:::-;111601:8;111611;111568:18;:52::i;:::-;111482:146;;:::o;112785:236::-;112899:31;112912:4;112918:2;112922:7;112899:12;:31::i;:::-;112941:72;112975:12;:10;:12::i;:::-;112989:4;112995:2;112999:7;113008:4;112941:33;:72::i;:::-;112785:236;;;;:::o;148134:36::-;;;;:::o;156760:612::-;156867:13;156926:1;156897:31;;:17;156906:7;156897:8;:17::i;:::-;:31;;;156893:116;;156989:7;156952:45;;;;;;;;;;;:::i;:::-;;;;;;;;156893:116;157021:28;157052:23;157067:7;157052:14;:23::i;:::-;157021:54;;157121:1;157096:14;157090:28;:32;157086:124;;;157146:14;157139:21;;;;;157086:124;157222:18;157243:10;:8;:10::i;:::-;157222:31;;157295:4;157301:18;:7;:16;:18::i;:::-;157278:51;;;;;;;;;:::i;:::-;;;;;;;;;;;;;157264:66;;;;156760:612;;;;:::o;147880:24::-;;;;:::o;149557:208::-;142917:13;:11;:13::i;:::-;149665:6:::1;149660:98;149681:5;;:12;;149677:1;:16;149660:98;;;149742:4;149715:14;:24;149730:5;;149736:1;149730:8;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;149715:24;;;;;;;;;;;;;;;;:31;;;;;;;;;;;;;;;;;;149695:3;;;;;;;149660:98;;;;149557:208:::0;;:::o;151295:112::-;142917:13;:11;:13::i;:::-;151394:5:::1;151371:20;:28;;;;151295:112:::0;:::o;111699:155::-;111787:4;111811:18;:25;111830:5;111811:25;;;;;;;;;;;;;;;:35;111837:8;111811:35;;;;;;;;;;;;;;;;;;;;;;;;;111804:42;;111699:155;;;;:::o;143964:220::-;142917:13;:11;:13::i;:::-;144069:1:::1;144049:22;;:8;:22;;::::0;144045:93:::1;;144123:1;144095:31;;;;;;;;;;;:::i;:::-;;;;;;;;144045:93;144148:28;144167:8;144148:18;:28::i;:::-;143964:220:::0;:::o;148948:101::-;142917:13;:11;:13::i;:::-;149032:9:::1;149019:10;:22;;;;148948:101:::0;:::o;140160:209::-;140262:4;139975:10;139968:18;;140286:35;;;:11;:35;;;;:75;;;;140325:36;140349:11;140325:23;:36::i;:::-;140286:75;140279:82;;140160:209;;;:::o;124303:247::-;124366:7;124386:13;124402:17;124411:7;124402:8;:17::i;:::-;124386:33;;124451:1;124434:19;;:5;:19;;;124430:90;;124500:7;124477:31;;;;;;;;;;;:::i;:::-;;;;;;;;124430:90;124537:5;124530:12;;;124303:247;;;:::o;113784:129::-;113854:7;113881:15;:24;113897:7;113881:24;;;;;;;;;;;;;;;;;;;;;113874:31;;113784:129;;;:::o;19768:98::-;19821:7;19848:10;19841:17;;19768:98;:::o;122535:122::-;122616:33;122625:2;122629:7;122638:4;122644;122616:8;:33::i;:::-;122535:122;;;:::o;143196:166::-;143267:12;:10;:12::i;:::-;143256:23;;:7;:5;:7::i;:::-;:23;;;143252:103;;143330:12;:10;:12::i;:::-;143303:40;;;;;;;;;;;:::i;:::-;;;;;;;;143252:103;143196:166::o;113546:117::-;113612:7;113639;:16;113647:7;113639:16;;;;;;;;;;;;;;;;;;;;;113632:23;;113546:117;;;:::o;141184:170::-;141298:9;141276:10;:19;141287:7;141276:19;;;;;;;;;;;:31;;;;;;:::i;:::-;;141323:23;141338:7;141323:23;;;;;;:::i;:::-;;;;;;;;141184:170;;:::o;157450:262::-;157640:7;157672:32;157686:2;157690:7;157699:4;157672:13;:32::i;:::-;157665:39;;157450:262;;;;;:::o;136752:120::-;135715:16;:14;:16::i;:::-;136821:5:::1;136811:7;;:15;;;;;;;;;;;;;;;;;;136842:22;136851:12;:10;:12::i;:::-;136842:22;;;;;;:::i;:::-;;;;;;;;136752:120::o:0;118603:102::-;118671:26;118681:2;118685:7;118671:26;;;;;;;;;;;;:9;:26::i;:::-;118603:102;;:::o;144344:191::-;144418:16;144437:6;;;;;;;;;;;144418:25;;144463:8;144454:6;;:17;;;;;;;;;;;;;;;;;;144518:8;144487:40;;144508:8;144487:40;;;;;;;;;;;;144407:128;144344:191;:::o;136493:118::-;135456:19;:17;:19::i;:::-;136563:4:::1;136553:7;;:14;;;;;;;;;;;;;;;;;;136583:20;136590:12;:10;:12::i;:::-;136583:20;;;;;;:::i;:::-;;;;;;;;136493:118::o:0;123742:318::-;123870:1;123850:22;;:8;:22;;;123846:93;;123918:8;123896:31;;;;;;;;;;;:::i;:::-;;;;;;;;123846:93;123987:8;123949:18;:25;123968:5;123949:25;;;;;;;;;;;;;;;:35;123975:8;123949:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;124033:8;124011:41;;124026:5;124011:41;;;124043:8;124011:41;;;;;;:::i;:::-;;;;;;;;123742:318;;;:::o;18118:948::-;18322:1;18305:2;:14;;;:18;18301:758;;;18360:2;18344:36;;;18381:8;18391:4;18397:7;18406:4;18344:67;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;18340:708;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18724:1;18707:6;:13;:18;18703:330;;18849:2;18813:39;;;;;;;;;;;:::i;:::-;;;;;;;;18703:330;18983:6;18977:13;18968:6;18964:2;18960:15;18953:38;18340:708;18469:41;;;18459:51;;;:6;:51;;;;18455:185;;18617:2;18581:39;;;;;;;;;;;:::i;:::-;;;;;;;;18455:185;18412:243;18301:758;18118:948;;;;;:::o;140440:609::-;140513:13;140539:22;140553:7;140539:13;:22::i;:::-;;140574:23;140600:10;:19;140611:7;140600:19;;;;;;;;;;;140574:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;140630:18;140651:10;:8;:10::i;:::-;140630:31;;140759:1;140743:4;140737:18;:23;140733:72;;140784:9;140777:16;;;;;;140733:72;140932:1;140912:9;140906:23;:27;140902:97;;;140971:4;140977:9;140957:30;;;;;;;;;:::i;:::-;;;;;;;;;;;;;140950:37;;;;;;140902:97;141018:23;141033:7;141018:14;:23::i;:::-;141011:30;;;;140440:609;;;;:::o;156530:106::-;156582:13;156615;156608:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;156530:106;:::o;90806:650::-;90862:13;90913:14;90950:1;90930:17;90941:5;90930:10;:17::i;:::-;:21;90913:38;;90966:20;91000:6;90989:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90966:41;;91022:11;91119:6;91115:2;91111:15;91103:6;91099:28;91092:35;;91156:254;91163:4;91156:254;;;91188:5;;;;;;;;91294:10;91289:2;91282:5;91278:14;91273:32;91268:3;91260:46;91352:2;91343:11;;;;;;:::i;:::-;;;;;91386:1;91377:5;:10;91156:254;91373:21;91156:254;91431:6;91424:13;;;;;90806:650;;;:::o;127866:224::-;127968:4;128007:35;127992:50;;;:11;:50;;;;:90;;;;128046:36;128070:11;128046:23;:36::i;:::-;127992:90;127985:97;;127866:224;;;:::o;122845:678::-;123007:9;:31;;;;123036:1;123020:18;;:4;:18;;;;123007:31;123003:471;;;123055:13;123071:22;123085:7;123071:13;:22::i;:::-;123055:38;;123240:1;123224:18;;:4;:18;;;;:35;;;;;123255:4;123246:13;;:5;:13;;;;123224:35;:69;;;;;123264:29;123281:5;123288:4;123264:16;:29::i;:::-;123263:30;123224:69;123220:144;;;123343:4;123321:27;;;;;;;;;;;:::i;:::-;;;;;;;;123220:144;123384:9;123380:83;;;123439:7;123435:2;123419:28;;123428:5;123419:28;;;;;;;;;;;;123380:83;123040:434;123003:471;123513:2;123486:15;:24;123502:7;123486:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;122845:678;;;;:::o;137985:210::-;138128:7;135456:19;:17;:19::i;:::-;138155:32:::1;138169:2;138173:7;138182:4;138155:13;:32::i;:::-;138148:39;;137985:210:::0;;;;;:::o;136219:130::-;136283:8;:6;:8::i;:::-;136278:64;;136315:15;;;;;;;;;;;;;;136278:64;136219:130::o;118932:210::-;119027:18;119033:2;119037:7;119027:5;:18::i;:::-;119056:78;119090:12;:10;:12::i;:::-;119112:1;119116:2;119120:7;119129:4;119056:33;:78::i;:::-;118932:210;;;:::o;136010:132::-;136076:8;:6;:8::i;:::-;136072:63;;;136108:15;;;;;;;;;;;;;;136072:63;136010:132::o;110406:260::-;110470:13;110496:22;110510:7;110496:13;:22::i;:::-;;110531:21;110555:10;:8;:10::i;:::-;110531:34;;110607:1;110589:7;110583:21;:25;:75;;;;;;;;;;;;;;;;;110625:7;110634:18;:7;:16;:18::i;:::-;110611:42;;;;;;;;;:::i;:::-;;;;;;;;;;;;;110583:75;110576:82;;;110406:260;;;:::o;84133:948::-;84186:7;84206:14;84223:1;84206:18;;84273:8;84264:5;:17;84260:106;;84311:8;84302:17;;;;;;:::i;:::-;;;;;84348:2;84338:12;;;;84260:106;84393:8;84384:5;:17;84380:106;;84431:8;84422:17;;;;;;:::i;:::-;;;;;84468:2;84458:12;;;;84380:106;84513:8;84504:5;:17;84500:106;;84551:8;84542:17;;;;;;:::i;:::-;;;;;84588:2;84578:12;;;;84500:106;84633:7;84624:5;:16;84620:103;;84670:7;84661:16;;;;;;:::i;:::-;;;;;84706:1;84696:11;;;;84620:103;84750:7;84741:5;:16;84737:103;;84787:7;84778:16;;;;;;:::i;:::-;;;;;84823:1;84813:11;;;;84737:103;84867:7;84858:5;:16;84854:103;;84904:7;84895:16;;;;;;:::i;:::-;;;;;84940:1;84930:11;;;;84854:103;84984:7;84975:5;:16;84971:68;;85022:1;85012:11;;;;84971:68;85067:6;85060:13;;;84133:948;;;:::o;109249:305::-;109351:4;109403:25;109388:40;;;:11;:40;;;;:105;;;;109460:33;109445:48;;;:11;:48;;;;109388:105;:158;;;;109510:36;109534:11;109510:23;:36::i;:::-;109388:158;109368:178;;109249:305;;;:::o;128983:640::-;129078:7;129098:21;129122:32;129136:2;129140:7;129149:4;129122:13;:32::i;:::-;129098:56;;129196:1;129171:27;;:13;:27;;;129167:214;;129215:40;129247:7;129215:31;:40::i;:::-;129167:214;;;129294:2;129277:19;;:13;:19;;;129273:108;;129313:56;129346:13;129361:7;129313:32;:56::i;:::-;129273:108;129167:214;129409:1;129395:16;;:2;:16;;;129391:192;;129428:45;129465:7;129428:36;:45::i;:::-;129391:192;;;129512:2;129495:19;;:13;:19;;;129491:92;;129531:40;129559:2;129563:7;129531:27;:40::i;:::-;129491:92;129391:192;129602:13;129595:20;;;128983:640;;;;;:::o;117905:335::-;117987:1;117973:16;;:2;:16;;;117969:89;;118043:1;118013:33;;;;;;;;;;;:::i;:::-;;;;;;;;117969:89;118068:21;118092:32;118100:2;118104:7;118121:1;118092:7;:32::i;:::-;118068:56;;118164:1;118139:27;;:13;:27;;;118135:98;;118218:1;118190:31;;;;;;;;;;;:::i;:::-;;;;;;;;118135:98;117958:282;117905:335;;:::o;107847:148::-;107923:4;107962:25;107947:40;;;:11;:40;;;;107940:47;;107847:148;;;:::o;116745:824::-;116831:7;116851:12;116866:17;116875:7;116866:8;:17::i;:::-;116851:32;;116962:1;116946:18;;:4;:18;;;116942:88;;116981:37;116998:4;117004;117010:7;116981:16;:37::i;:::-;116942:88;117093:1;117077:18;;:4;:18;;;117073:263;;117195:48;117212:1;117216:7;117233:1;117237:5;117195:8;:48::i;:::-;117308:1;117289:9;:15;117299:4;117289:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;117073:263;117366:1;117352:16;;:2;:16;;;117348:111;;117431:1;117414:9;:13;117424:2;117414:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;117348:111;117490:2;117471:7;:16;117479:7;117471:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;117529:7;117525:2;117510:27;;117519:4;117510:27;;;;;;;;;;;;117557:4;117550:11;;;116745:824;;;;;:::o;130343:164::-;130447:10;:17;;;;130420:15;:24;130436:7;130420:24;;;;;;;;;;;:44;;;;130475:10;130491:7;130475:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130343:164;:::o;131134:1075::-;131400:22;131425:15;131435:4;131425:9;:15::i;:::-;131400:40;;131451:18;131472:17;:26;131490:7;131472:26;;;;;;;;;;;;131451:47;;131511:61;131575:12;:18;131588:4;131575:18;;;;;;;;;;;;;;;131511:82;;131714:14;131700:10;:28;131696:330;;131745:19;131767;:35;131787:14;131767:35;;;;;;;;;;;;131745:57;;131853:11;131819:19;:31;131839:10;131819:31;;;;;;;;;;;:45;;;;131970:10;131937:17;:30;131955:11;131937:30;;;;;;;;;;;:43;;;;131730:296;131696:330;132122:17;:26;132140:7;132122:26;;;;;;;;;;;132115:33;;;132166:19;:35;132186:14;132166:35;;;;;;;;;;;132159:42;;;131215:994;;;131134:1075;;:::o;132504:1079::-;132757:22;132802:1;132782:10;:17;;;;:21;;;;:::i;:::-;132757:46;;132814:18;132835:15;:24;132851:7;132835:24;;;;;;;;;;;;132814:45;;133186:19;133208:10;133219:14;133208:26;;;;;;;;:::i;:::-;;;;;;;;;;133186:48;;133272:11;133247:10;133258;133247:22;;;;;;;;:::i;:::-;;;;;;;;;:36;;;;133383:10;133352:15;:28;133368:11;133352:28;;;;;;;;;;;:41;;;;133524:15;:24;133540:7;133524:24;;;;;;;;;;;133517:31;;;133559:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;132575:1008;;;132504:1079;:::o;129924:218::-;130009:14;130042:1;130026:13;130036:2;130026:9;:13::i;:::-;:17;;;;:::i;:::-;130009:34;;130081:7;130054:12;:16;130067:2;130054:16;;;;;;;;;;;;;;;:24;130071:6;130054:24;;;;;;;;;;;:34;;;;130128:6;130099:17;:26;130117:7;130099:26;;;;;;;;;;;:35;;;;129998:144;129924:218;;:::o;114952:376::-;115065:38;115079:5;115086:7;115095;115065:13;:38::i;:::-;115060:261;;115141:1;115124:19;;:5;:19;;;115120:190;;115194:7;115171:31;;;;;;;;;;;:::i;:::-;;;;;;;;115120:190;115277:7;115286;115250:44;;;;;;;;;;;;:::i;:::-;;;;;;;;115060:261;114952:376;;;:::o;114233:276::-;114336:4;114392:1;114373:21;;:7;:21;;;;:128;;;;;114421:7;114412:16;;:5;:16;;;:52;;;;114432:32;114449:5;114456:7;114432:16;:32::i;:::-;114412:52;:88;;;;114493:7;114468:32;;:21;114481:7;114468:12;:21::i;:::-;:32;;;114412:88;114373:128;114353:148;;114233:276;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:246::-;1879:1;1889:113;1903:6;1900:1;1897:13;1889:113;;;1988:1;1983:3;1979:11;1973:18;1969:1;1964:3;1960:11;1953:39;1925:2;1922:1;1918:10;1913:15;;1889:113;;;2036:1;2027:6;2022:3;2018:16;2011:27;1860:184;1798:246;;;:::o;2050:102::-;2091:6;2142:2;2138:7;2133:2;2126:5;2122:14;2118:28;2108:38;;2050:102;;;:::o;2158:377::-;2246:3;2274:39;2307:5;2274:39;:::i;:::-;2329:71;2393:6;2388:3;2329:71;:::i;:::-;2322:78;;2409:65;2467:6;2462:3;2455:4;2448:5;2444:16;2409:65;:::i;:::-;2499:29;2521:6;2499:29;:::i;:::-;2494:3;2490:39;2483:46;;2250:285;2158:377;;;;:::o;2541:313::-;2654:4;2692:2;2681:9;2677:18;2669:26;;2741:9;2735:4;2731:20;2727:1;2716:9;2712:17;2705:47;2769:78;2842:4;2833:6;2769:78;:::i;:::-;2761:86;;2541:313;;;;:::o;2860:77::-;2897:7;2926:5;2915:16;;2860:77;;;:::o;2943:122::-;3016:24;3034:5;3016:24;:::i;:::-;3009:5;3006:35;2996:63;;3055:1;3052;3045:12;2996:63;2943:122;:::o;3071:139::-;3117:5;3155:6;3142:20;3133:29;;3171:33;3198:5;3171:33;:::i;:::-;3071:139;;;;:::o;3216:329::-;3275:6;3324:2;3312:9;3303:7;3299:23;3295:32;3292:119;;;3330:79;;:::i;:::-;3292:119;3450:1;3475:53;3520:7;3511:6;3500:9;3496:22;3475:53;:::i;:::-;3465:63;;3421:117;3216:329;;;;:::o;3551:126::-;3588:7;3628:42;3621:5;3617:54;3606:65;;3551:126;;;:::o;3683:96::-;3720:7;3749:24;3767:5;3749:24;:::i;:::-;3738:35;;3683:96;;;:::o;3785:118::-;3872:24;3890:5;3872:24;:::i;:::-;3867:3;3860:37;3785:118;;:::o;3909:222::-;4002:4;4040:2;4029:9;4025:18;4017:26;;4053:71;4121:1;4110:9;4106:17;4097:6;4053:71;:::i;:::-;3909:222;;;;:::o;4137:122::-;4210:24;4228:5;4210:24;:::i;:::-;4203:5;4200:35;4190:63;;4249:1;4246;4239:12;4190:63;4137:122;:::o;4265:139::-;4311:5;4349:6;4336:20;4327:29;;4365:33;4392:5;4365:33;:::i;:::-;4265:139;;;;:::o;4410:474::-;4478:6;4486;4535:2;4523:9;4514:7;4510:23;4506:32;4503:119;;;4541:79;;:::i;:::-;4503:119;4661:1;4686:53;4731:7;4722:6;4711:9;4707:22;4686:53;:::i;:::-;4676:63;;4632:117;4788:2;4814:53;4859:7;4850:6;4839:9;4835:22;4814:53;:::i;:::-;4804:63;;4759:118;4410:474;;;;;:::o;4890:117::-;4999:1;4996;4989:12;5013:117;5122:1;5119;5112:12;5136:180;5184:77;5181:1;5174:88;5281:4;5278:1;5271:15;5305:4;5302:1;5295:15;5322:281;5405:27;5427:4;5405:27;:::i;:::-;5397:6;5393:40;5535:6;5523:10;5520:22;5499:18;5487:10;5484:34;5481:62;5478:88;;;5546:18;;:::i;:::-;5478:88;5586:10;5582:2;5575:22;5365:238;5322:281;;:::o;5609:129::-;5643:6;5670:20;;:::i;:::-;5660:30;;5699:33;5727:4;5719:6;5699:33;:::i;:::-;5609:129;;;:::o;5744:308::-;5806:4;5896:18;5888:6;5885:30;5882:56;;;5918:18;;:::i;:::-;5882:56;5956:29;5978:6;5956:29;:::i;:::-;5948:37;;6040:4;6034;6030:15;6022:23;;5744:308;;;:::o;6058:146::-;6155:6;6150:3;6145;6132:30;6196:1;6187:6;6182:3;6178:16;6171:27;6058:146;;;:::o;6210:425::-;6288:5;6313:66;6329:49;6371:6;6329:49;:::i;:::-;6313:66;:::i;:::-;6304:75;;6402:6;6395:5;6388:21;6440:4;6433:5;6429:16;6478:3;6469:6;6464:3;6460:16;6457:25;6454:112;;;6485:79;;:::i;:::-;6454:112;6575:54;6622:6;6617:3;6612;6575:54;:::i;:::-;6294:341;6210:425;;;;;:::o;6655:340::-;6711:5;6760:3;6753:4;6745:6;6741:17;6737:27;6727:122;;6768:79;;:::i;:::-;6727:122;6885:6;6872:20;6910:79;6985:3;6977:6;6970:4;6962:6;6958:17;6910:79;:::i;:::-;6901:88;;6717:278;6655:340;;;;:::o;7001:654::-;7079:6;7087;7136:2;7124:9;7115:7;7111:23;7107:32;7104:119;;;7142:79;;:::i;:::-;7104:119;7262:1;7287:53;7332:7;7323:6;7312:9;7308:22;7287:53;:::i;:::-;7277:63;;7233:117;7417:2;7406:9;7402:18;7389:32;7448:18;7440:6;7437:30;7434:117;;;7470:79;;:::i;:::-;7434:117;7575:63;7630:7;7621:6;7610:9;7606:22;7575:63;:::i;:::-;7565:73;;7360:288;7001:654;;;;;:::o;7661:118::-;7748:24;7766:5;7748:24;:::i;:::-;7743:3;7736:37;7661:118;;:::o;7785:222::-;7878:4;7916:2;7905:9;7901:18;7893:26;;7929:71;7997:1;7986:9;7982:17;7973:6;7929:71;:::i;:::-;7785:222;;;;:::o;8013:619::-;8090:6;8098;8106;8155:2;8143:9;8134:7;8130:23;8126:32;8123:119;;;8161:79;;:::i;:::-;8123:119;8281:1;8306:53;8351:7;8342:6;8331:9;8327:22;8306:53;:::i;:::-;8296:63;;8252:117;8408:2;8434:53;8479:7;8470:6;8459:9;8455:22;8434:53;:::i;:::-;8424:63;;8379:118;8536:2;8562:53;8607:7;8598:6;8587:9;8583:22;8562:53;:::i;:::-;8552:63;;8507:118;8013:619;;;;;:::o;8638:329::-;8697:6;8746:2;8734:9;8725:7;8721:23;8717:32;8714:119;;;8752:79;;:::i;:::-;8714:119;8872:1;8897:53;8942:7;8933:6;8922:9;8918:22;8897:53;:::i;:::-;8887:63;;8843:117;8638:329;;;;:::o;8973:114::-;9040:6;9074:5;9068:12;9058:22;;8973:114;;;:::o;9093:184::-;9192:11;9226:6;9221:3;9214:19;9266:4;9261:3;9257:14;9242:29;;9093:184;;;;:::o;9283:132::-;9350:4;9373:3;9365:11;;9403:4;9398:3;9394:14;9386:22;;9283:132;;;:::o;9421:108::-;9498:24;9516:5;9498:24;:::i;:::-;9493:3;9486:37;9421:108;;:::o;9535:179::-;9604:10;9625:46;9667:3;9659:6;9625:46;:::i;:::-;9703:4;9698:3;9694:14;9680:28;;9535:179;;;;:::o;9720:113::-;9790:4;9822;9817:3;9813:14;9805:22;;9720:113;;;:::o;9869:732::-;9988:3;10017:54;10065:5;10017:54;:::i;:::-;10087:86;10166:6;10161:3;10087:86;:::i;:::-;10080:93;;10197:56;10247:5;10197:56;:::i;:::-;10276:7;10307:1;10292:284;10317:6;10314:1;10311:13;10292:284;;;10393:6;10387:13;10420:63;10479:3;10464:13;10420:63;:::i;:::-;10413:70;;10506:60;10559:6;10506:60;:::i;:::-;10496:70;;10352:224;10339:1;10336;10332:9;10327:14;;10292:284;;;10296:14;10592:3;10585:10;;9993:608;;;9869:732;;;;:::o;10607:373::-;10750:4;10788:2;10777:9;10773:18;10765:26;;10837:9;10831:4;10827:20;10823:1;10812:9;10808:17;10801:47;10865:108;10968:4;10959:6;10865:108;:::i;:::-;10857:116;;10607:373;;;;:::o;10986:509::-;11055:6;11104:2;11092:9;11083:7;11079:23;11075:32;11072:119;;;11110:79;;:::i;:::-;11072:119;11258:1;11247:9;11243:17;11230:31;11288:18;11280:6;11277:30;11274:117;;;11310:79;;:::i;:::-;11274:117;11415:63;11470:7;11461:6;11450:9;11446:22;11415:63;:::i;:::-;11405:73;;11201:287;10986:509;;;;:::o;11501:116::-;11571:21;11586:5;11571:21;:::i;:::-;11564:5;11561:32;11551:60;;11607:1;11604;11597:12;11551:60;11501:116;:::o;11623:133::-;11666:5;11704:6;11691:20;11682:29;;11720:30;11744:5;11720:30;:::i;:::-;11623:133;;;;:::o;11762:468::-;11827:6;11835;11884:2;11872:9;11863:7;11859:23;11855:32;11852:119;;;11890:79;;:::i;:::-;11852:119;12010:1;12035:53;12080:7;12071:6;12060:9;12056:22;12035:53;:::i;:::-;12025:63;;11981:117;12137:2;12163:50;12205:7;12196:6;12185:9;12181:22;12163:50;:::i;:::-;12153:60;;12108:115;11762:468;;;;;:::o;12236:307::-;12297:4;12387:18;12379:6;12376:30;12373:56;;;12409:18;;:::i;:::-;12373:56;12447:29;12469:6;12447:29;:::i;:::-;12439:37;;12531:4;12525;12521:15;12513:23;;12236:307;;;:::o;12549:423::-;12626:5;12651:65;12667:48;12708:6;12667:48;:::i;:::-;12651:65;:::i;:::-;12642:74;;12739:6;12732:5;12725:21;12777:4;12770:5;12766:16;12815:3;12806:6;12801:3;12797:16;12794:25;12791:112;;;12822:79;;:::i;:::-;12791:112;12912:54;12959:6;12954:3;12949;12912:54;:::i;:::-;12632:340;12549:423;;;;;:::o;12991:338::-;13046:5;13095:3;13088:4;13080:6;13076:17;13072:27;13062:122;;13103:79;;:::i;:::-;13062:122;13220:6;13207:20;13245:78;13319:3;13311:6;13304:4;13296:6;13292:17;13245:78;:::i;:::-;13236:87;;13052:277;12991:338;;;;:::o;13335:943::-;13430:6;13438;13446;13454;13503:3;13491:9;13482:7;13478:23;13474:33;13471:120;;;13510:79;;:::i;:::-;13471:120;13630:1;13655:53;13700:7;13691:6;13680:9;13676:22;13655:53;:::i;:::-;13645:63;;13601:117;13757:2;13783:53;13828:7;13819:6;13808:9;13804:22;13783:53;:::i;:::-;13773:63;;13728:118;13885:2;13911:53;13956:7;13947:6;13936:9;13932:22;13911:53;:::i;:::-;13901:63;;13856:118;14041:2;14030:9;14026:18;14013:32;14072:18;14064:6;14061:30;14058:117;;;14094:79;;:::i;:::-;14058:117;14199:62;14253:7;14244:6;14233:9;14229:22;14199:62;:::i;:::-;14189:72;;13984:287;13335:943;;;;;;;:::o;14284:117::-;14393:1;14390;14383:12;14407:117;14516:1;14513;14506:12;14547:568;14620:8;14630:6;14680:3;14673:4;14665:6;14661:17;14657:27;14647:122;;14688:79;;:::i;:::-;14647:122;14801:6;14788:20;14778:30;;14831:18;14823:6;14820:30;14817:117;;;14853:79;;:::i;:::-;14817:117;14967:4;14959:6;14955:17;14943:29;;15021:3;15013:4;15005:6;15001:17;14991:8;14987:32;14984:41;14981:128;;;15028:79;;:::i;:::-;14981:128;14547:568;;;;;:::o;15121:559::-;15207:6;15215;15264:2;15252:9;15243:7;15239:23;15235:32;15232:119;;;15270:79;;:::i;:::-;15232:119;15418:1;15407:9;15403:17;15390:31;15448:18;15440:6;15437:30;15434:117;;;15470:79;;:::i;:::-;15434:117;15583:80;15655:7;15646:6;15635:9;15631:22;15583:80;:::i;:::-;15565:98;;;;15361:312;15121:559;;;;;:::o;15686:474::-;15754:6;15762;15811:2;15799:9;15790:7;15786:23;15782:32;15779:119;;;15817:79;;:::i;:::-;15779:119;15937:1;15962:53;16007:7;15998:6;15987:9;15983:22;15962:53;:::i;:::-;15952:63;;15908:117;16064:2;16090:53;16135:7;16126:6;16115:9;16111:22;16090:53;:::i;:::-;16080:63;;16035:118;15686:474;;;;;:::o;16166:180::-;16214:77;16211:1;16204:88;16311:4;16308:1;16301:15;16335:4;16332:1;16325:15;16352:320;16396:6;16433:1;16427:4;16423:12;16413:22;;16480:1;16474:4;16470:12;16501:18;16491:81;;16557:4;16549:6;16545:17;16535:27;;16491:81;16619:2;16611:6;16608:14;16588:18;16585:38;16582:84;;16638:18;;:::i;:::-;16582:84;16403:269;16352:320;;;:::o;16678:442::-;16827:4;16865:2;16854:9;16850:18;16842:26;;16878:71;16946:1;16935:9;16931:17;16922:6;16878:71;:::i;:::-;16959:72;17027:2;17016:9;17012:18;17003:6;16959:72;:::i;:::-;17041;17109:2;17098:9;17094:18;17085:6;17041:72;:::i;:::-;16678:442;;;;;;:::o;17126:332::-;17247:4;17285:2;17274:9;17270:18;17262:26;;17298:71;17366:1;17355:9;17351:17;17342:6;17298:71;:::i;:::-;17379:72;17447:2;17436:9;17432:18;17423:6;17379:72;:::i;:::-;17126:332;;;;;:::o;17464:170::-;17604:22;17600:1;17592:6;17588:14;17581:46;17464:170;:::o;17640:366::-;17782:3;17803:67;17867:2;17862:3;17803:67;:::i;:::-;17796:74;;17879:93;17968:3;17879:93;:::i;:::-;17997:2;17992:3;17988:12;17981:19;;17640:366;;;:::o;18012:419::-;18178:4;18216:2;18205:9;18201:18;18193:26;;18265:9;18259:4;18255:20;18251:1;18240:9;18236:17;18229:47;18293:131;18419:4;18293:131;:::i;:::-;18285:139;;18012:419;;;:::o;18437:147::-;18538:11;18575:3;18560:18;;18437:147;;;;:::o;18590:114::-;;:::o;18710:398::-;18869:3;18890:83;18971:1;18966:3;18890:83;:::i;:::-;18883:90;;18982:93;19071:3;18982:93;:::i;:::-;19100:1;19095:3;19091:11;19084:18;;18710:398;;;:::o;19114:379::-;19298:3;19320:147;19463:3;19320:147;:::i;:::-;19313:154;;19484:3;19477:10;;19114:379;;;:::o;19499:167::-;19639:19;19635:1;19627:6;19623:14;19616:43;19499:167;:::o;19672:366::-;19814:3;19835:67;19899:2;19894:3;19835:67;:::i;:::-;19828:74;;19911:93;20000:3;19911:93;:::i;:::-;20029:2;20024:3;20020:12;20013:19;;19672:366;;;:::o;20044:419::-;20210:4;20248:2;20237:9;20233:18;20225:26;;20297:9;20291:4;20287:20;20283:1;20272:9;20268:17;20261:47;20325:131;20451:4;20325:131;:::i;:::-;20317:139;;20044:419;;;:::o;20469:180::-;20517:77;20514:1;20507:88;20614:4;20611:1;20604:15;20638:4;20635:1;20628:15;20655:233;20694:3;20717:24;20735:5;20717:24;:::i;:::-;20708:33;;20763:66;20756:5;20753:77;20750:103;;20833:18;;:::i;:::-;20750:103;20880:1;20873:5;20869:13;20862:20;;20655:233;;;:::o;20894:191::-;20934:3;20953:20;20971:1;20953:20;:::i;:::-;20948:25;;20987:20;21005:1;20987:20;:::i;:::-;20982:25;;21030:1;21027;21023:9;21016:16;;21051:3;21048:1;21045:10;21042:36;;;21058:18;;:::i;:::-;21042:36;20894:191;;;;:::o;21091:168::-;21231:20;21227:1;21219:6;21215:14;21208:44;21091:168;:::o;21265:366::-;21407:3;21428:67;21492:2;21487:3;21428:67;:::i;:::-;21421:74;;21504:93;21593:3;21504:93;:::i;:::-;21622:2;21617:3;21613:12;21606:19;;21265:366;;;:::o;21637:419::-;21803:4;21841:2;21830:9;21826:18;21818:26;;21890:9;21884:4;21880:20;21876:1;21865:9;21861:17;21854:47;21918:131;22044:4;21918:131;:::i;:::-;21910:139;;21637:419;;;:::o;22062:180::-;22110:77;22107:1;22100:88;22207:4;22204:1;22197:15;22231:4;22228:1;22221:15;22248:141;22297:4;22320:3;22312:11;;22343:3;22340:1;22333:14;22377:4;22374:1;22364:18;22356:26;;22248:141;;;:::o;22395:93::-;22432:6;22479:2;22474;22467:5;22463:14;22459:23;22449:33;;22395:93;;;:::o;22494:107::-;22538:8;22588:5;22582:4;22578:16;22557:37;;22494:107;;;;:::o;22607:393::-;22676:6;22726:1;22714:10;22710:18;22749:97;22779:66;22768:9;22749:97;:::i;:::-;22867:39;22897:8;22886:9;22867:39;:::i;:::-;22855:51;;22939:4;22935:9;22928:5;22924:21;22915:30;;22988:4;22978:8;22974:19;22967:5;22964:30;22954:40;;22683:317;;22607:393;;;;;:::o;23006:60::-;23034:3;23055:5;23048:12;;23006:60;;;:::o;23072:142::-;23122:9;23155:53;23173:34;23182:24;23200:5;23182:24;:::i;:::-;23173:34;:::i;:::-;23155:53;:::i;:::-;23142:66;;23072:142;;;:::o;23220:75::-;23263:3;23284:5;23277:12;;23220:75;;;:::o;23301:269::-;23411:39;23442:7;23411:39;:::i;:::-;23472:91;23521:41;23545:16;23521:41;:::i;:::-;23513:6;23506:4;23500:11;23472:91;:::i;:::-;23466:4;23459:105;23377:193;23301:269;;;:::o;23576:73::-;23621:3;23576:73;:::o;23655:189::-;23732:32;;:::i;:::-;23773:65;23831:6;23823;23817:4;23773:65;:::i;:::-;23708:136;23655:189;;:::o;23850:186::-;23910:120;23927:3;23920:5;23917:14;23910:120;;;23981:39;24018:1;24011:5;23981:39;:::i;:::-;23954:1;23947:5;23943:13;23934:22;;23910:120;;;23850:186;;:::o;24042:543::-;24143:2;24138:3;24135:11;24132:446;;;24177:38;24209:5;24177:38;:::i;:::-;24261:29;24279:10;24261:29;:::i;:::-;24251:8;24247:44;24444:2;24432:10;24429:18;24426:49;;;24465:8;24450:23;;24426:49;24488:80;24544:22;24562:3;24544:22;:::i;:::-;24534:8;24530:37;24517:11;24488:80;:::i;:::-;24147:431;;24132:446;24042:543;;;:::o;24591:117::-;24645:8;24695:5;24689:4;24685:16;24664:37;;24591:117;;;;:::o;24714:169::-;24758:6;24791:51;24839:1;24835:6;24827:5;24824:1;24820:13;24791:51;:::i;:::-;24787:56;24872:4;24866;24862:15;24852:25;;24765:118;24714:169;;;;:::o;24888:295::-;24964:4;25110:29;25135:3;25129:4;25110:29;:::i;:::-;25102:37;;25172:3;25169:1;25165:11;25159:4;25156:21;25148:29;;24888:295;;;;:::o;25188:1395::-;25305:37;25338:3;25305:37;:::i;:::-;25407:18;25399:6;25396:30;25393:56;;;25429:18;;:::i;:::-;25393:56;25473:38;25505:4;25499:11;25473:38;:::i;:::-;25558:67;25618:6;25610;25604:4;25558:67;:::i;:::-;25652:1;25676:4;25663:17;;25708:2;25700:6;25697:14;25725:1;25720:618;;;;26382:1;26399:6;26396:77;;;26448:9;26443:3;26439:19;26433:26;26424:35;;26396:77;26499:67;26559:6;26552:5;26499:67;:::i;:::-;26493:4;26486:81;26355:222;25690:887;;25720:618;25772:4;25768:9;25760:6;25756:22;25806:37;25838:4;25806:37;:::i;:::-;25865:1;25879:208;25893:7;25890:1;25887:14;25879:208;;;25972:9;25967:3;25963:19;25957:26;25949:6;25942:42;26023:1;26015:6;26011:14;26001:24;;26070:2;26059:9;26055:18;26042:31;;25916:4;25913:1;25909:12;25904:17;;25879:208;;;26115:6;26106:7;26103:19;26100:179;;;26173:9;26168:3;26164:19;26158:26;26216:48;26258:4;26250:6;26246:17;26235:9;26216:48;:::i;:::-;26208:6;26201:64;26123:156;26100:179;26325:1;26321;26313:6;26309:14;26305:22;26299:4;26292:36;25727:611;;;25690:887;;25280:1303;;;25188:1395;;:::o;26589:178::-;26729:30;26725:1;26717:6;26713:14;26706:54;26589:178;:::o;26773:366::-;26915:3;26936:67;27000:2;26995:3;26936:67;:::i;:::-;26929:74;;27012:93;27101:3;27012:93;:::i;:::-;27130:2;27125:3;27121:12;27114:19;;26773:366;;;:::o;27145:419::-;27311:4;27349:2;27338:9;27334:18;27326:26;;27398:9;27392:4;27388:20;27384:1;27373:9;27369:17;27362:47;27426:131;27552:4;27426:131;:::i;:::-;27418:139;;27145:419;;;:::o;27570:410::-;27610:7;27633:20;27651:1;27633:20;:::i;:::-;27628:25;;27667:20;27685:1;27667:20;:::i;:::-;27662:25;;27722:1;27719;27715:9;27744:30;27762:11;27744:30;:::i;:::-;27733:41;;27923:1;27914:7;27910:15;27907:1;27904:22;27884:1;27877:9;27857:83;27834:139;;27953:18;;:::i;:::-;27834:139;27618:362;27570:410;;;;:::o;27986:148::-;28088:11;28125:3;28110:18;;27986:148;;;;:::o;28140:390::-;28246:3;28274:39;28307:5;28274:39;:::i;:::-;28329:89;28411:6;28406:3;28329:89;:::i;:::-;28322:96;;28427:65;28485:6;28480:3;28473:4;28466:5;28462:16;28427:65;:::i;:::-;28517:6;28512:3;28508:16;28501:23;;28250:280;28140:390;;;;:::o;28536:155::-;28676:7;28672:1;28664:6;28660:14;28653:31;28536:155;:::o;28697:400::-;28857:3;28878:84;28960:1;28955:3;28878:84;:::i;:::-;28871:91;;28971:93;29060:3;28971:93;:::i;:::-;29089:1;29084:3;29080:11;29073:18;;28697:400;;;:::o;29103:701::-;29384:3;29406:95;29497:3;29488:6;29406:95;:::i;:::-;29399:102;;29518:95;29609:3;29600:6;29518:95;:::i;:::-;29511:102;;29630:148;29774:3;29630:148;:::i;:::-;29623:155;;29795:3;29788:10;;29103:701;;;;;:::o;29810:98::-;29861:6;29895:5;29889:12;29879:22;;29810:98;;;:::o;29914:168::-;29997:11;30031:6;30026:3;30019:19;30071:4;30066:3;30062:14;30047:29;;29914:168;;;;:::o;30088:373::-;30174:3;30202:38;30234:5;30202:38;:::i;:::-;30256:70;30319:6;30314:3;30256:70;:::i;:::-;30249:77;;30335:65;30393:6;30388:3;30381:4;30374:5;30370:16;30335:65;:::i;:::-;30425:29;30447:6;30425:29;:::i;:::-;30420:3;30416:39;30409:46;;30178:283;30088:373;;;;:::o;30467:640::-;30662:4;30700:3;30689:9;30685:19;30677:27;;30714:71;30782:1;30771:9;30767:17;30758:6;30714:71;:::i;:::-;30795:72;30863:2;30852:9;30848:18;30839:6;30795:72;:::i;:::-;30877;30945:2;30934:9;30930:18;30921:6;30877:72;:::i;:::-;30996:9;30990:4;30986:20;30981:2;30970:9;30966:18;30959:48;31024:76;31095:4;31086:6;31024:76;:::i;:::-;31016:84;;30467:640;;;;;;;:::o;31113:141::-;31169:5;31200:6;31194:13;31185:22;;31216:32;31242:5;31216:32;:::i;:::-;31113:141;;;;:::o;31260:349::-;31329:6;31378:2;31366:9;31357:7;31353:23;31349:32;31346:119;;;31384:79;;:::i;:::-;31346:119;31504:1;31529:63;31584:7;31575:6;31564:9;31560:22;31529:63;:::i;:::-;31519:73;;31475:127;31260:349;;;;:::o;31615:435::-;31795:3;31817:95;31908:3;31899:6;31817:95;:::i;:::-;31810:102;;31929:95;32020:3;32011:6;31929:95;:::i;:::-;31922:102;;32041:3;32034:10;;31615:435;;;;;:::o;32056:180::-;32104:77;32101:1;32094:88;32201:4;32198:1;32191:15;32225:4;32222:1;32215:15;32242:194;32282:4;32302:20;32320:1;32302:20;:::i;:::-;32297:25;;32336:20;32354:1;32336:20;:::i;:::-;32331:25;;32380:1;32377;32373:9;32365:17;;32404:1;32398:4;32395:11;32392:37;;;32409:18;;:::i;:::-;32392:37;32242:194;;;;:::o;32442:180::-;32490:77;32487:1;32480:88;32587:4;32584:1;32577:15;32611:4;32608:1;32601:15
Swarm Source
ipfs://649a70b36c0f950bcf5805f7cb5a393f9f7e7e3b486bf805358a6aad0eb8186f
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in S
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
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.