Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 88 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Mint With Token | 24641636 | 2 days ago | IN | 0 ETH | 0.00045465 | ||||
| Set Token Uri | 24641413 | 2 days ago | IN | 0 ETH | 0.00002724 | ||||
| Set Token Uri | 24641397 | 2 days ago | IN | 0 ETH | 0.00000914 | ||||
| Set Token Uri | 24641374 | 2 days ago | IN | 0 ETH | 0.00001693 | ||||
| Set Token Uri | 24641366 | 2 days ago | IN | 0 ETH | 0.0000155 | ||||
| Set Token Uri | 24641336 | 2 days ago | IN | 0 ETH | 0.0000121 | ||||
| Set Token Uri | 24641333 | 2 days ago | IN | 0 ETH | 0.00001319 | ||||
| Set Token Uri | 24641330 | 2 days ago | IN | 0 ETH | 0.00001442 | ||||
| Set Token Uri | 24641325 | 2 days ago | IN | 0 ETH | 0.00001448 | ||||
| Set Token Uri | 24641295 | 2 days ago | IN | 0 ETH | 0.00001274 | ||||
| Set Token Uri | 24641284 | 2 days ago | IN | 0 ETH | 0.00001327 | ||||
| Set Token Uri | 24641271 | 2 days ago | IN | 0 ETH | 0.00001481 | ||||
| Set Token Uri | 24641262 | 2 days ago | IN | 0 ETH | 0.0000056 | ||||
| Set Token Uri | 24641244 | 2 days ago | IN | 0 ETH | 0.000016 | ||||
| Set Token Uri | 24641146 | 2 days ago | IN | 0 ETH | 0.00000683 | ||||
| Set Token Uri | 24641132 | 2 days ago | IN | 0 ETH | 0.0000231 | ||||
| Set Token Uri | 24641109 | 2 days ago | IN | 0 ETH | 0.00002301 | ||||
| Set Token Uri | 24641075 | 2 days ago | IN | 0 ETH | 0.00001396 | ||||
| Set Token Uri | 24641069 | 2 days ago | IN | 0 ETH | 0.00000384 | ||||
| Set Token Uri | 24641065 | 2 days ago | IN | 0 ETH | 0.0000118 | ||||
| Set Token Uri | 24641061 | 2 days ago | IN | 0 ETH | 0.00001131 | ||||
| Set Type Token P... | 24640953 | 2 days ago | IN | 0 ETH | 0.00000257 | ||||
| Set Type Token P... | 24640947 | 2 days ago | IN | 0 ETH | 0.00000381 | ||||
| Set Type Token P... | 24640926 | 2 days ago | IN | 0 ETH | 0.000003 | ||||
| Set Type Token P... | 24640910 | 2 days ago | IN | 0 ETH | 0.00000191 |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AureonPrimeNFT
Compiler Version
v0.8.32+commit.ebbd65e5
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2026-03-11
*/
// File: @openzeppelin/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: @openzeppelin/contracts/token/ERC1155/IERC1155.sol
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/IERC1155.sol)
pragma solidity >=0.6.2;
/**
* @dev Required interface of an ERC-1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[ERC].
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the value of tokens of token type `id` owned by `account`.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the zero address.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `value` amount.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.
*
* Requirements:
*
* - `ids` and `values` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external;
}
// File: @openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)
pragma solidity >=0.6.2;
/**
* @dev Interface of the optional ERC1155MetadataExtension interface, as defined
* in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC].
*/
interface IERC1155MetadataURI is IERC1155 {
/**
* @dev Returns the URI for token type `id`.
*
* If the `\{id\}` substring is present in the URI, it must be replaced by
* clients with the actual token type ID.
*/
function uri(uint256 id) external view returns (string memory);
}
// File: @openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity >=0.6.2;
/**
* @dev Interface that must be implemented by smart contracts in order to receive
* ERC-1155 token transfers.
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC-1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC-1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
// File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol
// OpenZeppelin Contracts (last updated v5.5.0) (interfaces/draft-IERC6093.sol)
pragma solidity >=0.8.4;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-721.
* 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/ERC1155/utils/ERC1155Utils.sol
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC1155/utils/ERC1155Utils.sol)
pragma solidity ^0.8.20;
/**
* @dev Library that provide common ERC-1155 utility functions.
*
* See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155].
*
* _Available since v5.1._
*/
library ERC1155Utils {
/**
* @dev Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received}
* 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 {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept
* the transfer.
*/
function checkOnERC1155Received(
address operator,
address from,
address to,
uint256 id,
uint256 value,
bytes memory data
) internal {
if (to.code.length > 0) {
try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {
if (response != IERC1155Receiver.onERC1155Received.selector) {
// Tokens rejected
revert IERC1155Errors.ERC1155InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
// non-IERC1155Receiver implementer
revert IERC1155Errors.ERC1155InvalidReceiver(to);
} else {
assembly ("memory-safe") {
revert(add(reason, 0x20), mload(reason))
}
}
}
}
}
/**
* @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived}
* 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 {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept
* the transfer.
*/
function checkOnERC1155BatchReceived(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal {
if (to.code.length > 0) {
try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (
bytes4 response
) {
if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
// Tokens rejected
revert IERC1155Errors.ERC1155InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
// non-IERC1155Receiver implementer
revert IERC1155Errors.ERC1155InvalidReceiver(to);
} else {
assembly ("memory-safe") {
revert(add(reason, 0x20), 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/introspection/ERC165.sol
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
// File: @openzeppelin/contracts/utils/Comparators.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides a set of functions to compare values.
*
* _Available since v5.1._
*/
library Comparators {
function lt(uint256 a, uint256 b) internal pure returns (bool) {
return a < b;
}
function gt(uint256 a, uint256 b) internal pure returns (bool) {
return a > b;
}
}
// File: @openzeppelin/contracts/utils/SlotDerivation.sol
// OpenZeppelin Contracts (last updated v5.5.0) (utils/SlotDerivation.sol)
// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.
pragma solidity ^0.8.20;
/**
* @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots
* corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by
* the solidity language / compiler.
*
* See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.].
*
* Example usage:
* ```solidity
* contract Example {
* // Add the library methods
* using StorageSlot for bytes32;
* using SlotDerivation for *;
*
* // Declare a namespace
* string private constant _NAMESPACE = "<namespace>"; // eg. OpenZeppelin.Slot
*
* function setValueInNamespace(uint256 key, address newValue) internal {
* _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;
* }
*
* function getValueInNamespace(uint256 key) internal view returns (address) {
* return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;
* }
* }
* ```
*
* TIP: Consider using this library along with {StorageSlot}.
*
* NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking
* upgrade safety will ignore the slots accessed through this library.
*
* _Available since v5.1._
*/
library SlotDerivation {
/**
* @dev Derive an ERC-7201 slot from a string (namespace).
*/
function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {
assembly ("memory-safe") {
mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))
slot := and(keccak256(0x00, 0x20), not(0xff))
}
}
/**
* @dev Add an offset to a slot to get the n-th element of a structure or an array.
*/
function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {
unchecked {
return bytes32(uint256(slot) + pos);
}
}
/**
* @dev Derive the location of the first element in an array from the slot where the length is stored.
*/
function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, slot)
result := keccak256(0x00, 0x20)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, and(key, shr(96, not(0))))
mstore(0x20, slot)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, iszero(iszero(key)))
mstore(0x20, slot)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, key)
mstore(0x20, slot)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, key)
mstore(0x20, slot)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, key)
mstore(0x20, slot)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
let length := mload(key)
let begin := add(key, 0x20)
let end := add(begin, length)
let cache := mload(end)
mstore(end, slot)
result := keccak256(begin, add(length, 0x20))
mstore(end, cache)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
let length := mload(key)
let begin := add(key, 0x20)
let end := add(begin, length)
let cache := mload(end)
mstore(end, slot)
result := keccak256(begin, add(length, 0x20))
mstore(end, cache)
}
}
}
// File: @openzeppelin/contracts/utils/StorageSlot.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC-1967 implementation slot:
* ```solidity
* contract ERC1967 {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct Int256Slot {
int256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Int256Slot` with member `value` located at `slot`.
*/
function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
/**
* @dev Returns a `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
}
// 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.6.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 a uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in a 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 A 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.6.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
*/
function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
assembly ("memory-safe") {
low := add(a, b)
high := lt(low, a)
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
*/
function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = high * 2²⁵⁶ + low.
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
low := mul(a, b)
high := sub(sub(mm, low), lt(mm, low))
}
}
/**
* @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
success = c >= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a - b;
success = c <= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a * b;
assembly ("memory-safe") {
// Only true when the multiplication doesn't overflow
// (c / a == b) || (a == 0)
success := or(eq(div(c, a), b), iszero(a))
}
// equivalent to: success ? c : 0
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `DIV` opcode returns zero when the denominator is 0.
result := div(a, b)
}
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `MOD` opcode returns zero when the denominator is 0.
result := mod(a, b)
}
}
}
/**
* @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryAdd(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
*/
function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
(, uint256 result) = trySub(a, b);
return result;
}
/**
* @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryMul(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Branchless ternary evaluation for `condition ? a : b`. 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. `condition ? a : b`) 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) {
unchecked {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (high == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return low / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= high) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [high low].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
high := sub(high, gt(remainder, low))
low := sub(low, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly ("memory-safe") {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [high low] by twos.
low := div(low, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from high into low.
low |= high * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
// is no longer required.
result = low * inverse;
return result;
}
}
/**
* @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
*/
function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
if (high >= 1 << n) {
Panic.panic(Panic.UNDER_OVERFLOW);
}
return (high << (256 - n)) | (low >> n);
}
}
/**
* @dev Calculates x * y >> n with full precision, following the selected rounding direction.
*/
function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory buffer) private pure returns (bool) {
uint256 chunk;
for (uint256 i = 0; i < buffer.length; i += 0x20) {
// See _unsafeReadBytesOffset from utils/Bytes.sol
assembly ("memory-safe") {
chunk := mload(add(add(buffer, 0x20), i))
}
if (chunk >> (8 * saturatingSub(i + 0x20, buffer.length)) != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;
// Shifts value right by the current result and use it as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the first 16 bytes (most significant half).
assembly ("memory-safe") {
r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
}
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
/**
* @dev Counts the number of leading zero bits in a uint256.
*/
function clz(uint256 x) internal pure returns (uint256) {
return ternary(x == 0, 256, 255 - log2(x));
}
}
// File: @openzeppelin/contracts/utils/Arrays.sol
// OpenZeppelin Contracts (last updated v5.6.0) (utils/Arrays.sol)
// This file was procedurally generated from scripts/generate/templates/Arrays.js.
pragma solidity ^0.8.24;
/**
* @dev Collection of functions related to array types.
*/
library Arrays {
using SlotDerivation for bytes32;
using StorageSlot for bytes32;
/**
* @dev Sort an array of uint256 (in memory) following the provided comparator function.
*
* This function does the sorting "in place", meaning that it overrides the input. The object is returned for
* convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
*
* NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
* array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
* when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
* consume more gas than is available in a block, leading to potential DoS.
*
* IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
*/
function sort(
uint256[] memory array,
function(uint256, uint256) pure returns (bool) comp
) internal pure returns (uint256[] memory) {
_quickSort(_begin(array), _end(array), comp);
return array;
}
/**
* @dev Variant of {sort} that sorts an array of uint256 in increasing order.
*/
function sort(uint256[] memory array) internal pure returns (uint256[] memory) {
sort(array, Comparators.lt);
return array;
}
/**
* @dev Sort an array of address (in memory) following the provided comparator function.
*
* This function does the sorting "in place", meaning that it overrides the input. The object is returned for
* convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
*
* NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
* array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
* when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
* consume more gas than is available in a block, leading to potential DoS.
*
* IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
*/
function sort(
address[] memory array,
function(address, address) pure returns (bool) comp
) internal pure returns (address[] memory) {
sort(_castToUint256Array(array), _castToUint256Comp(comp));
return array;
}
/**
* @dev Variant of {sort} that sorts an array of address in increasing order.
*/
function sort(address[] memory array) internal pure returns (address[] memory) {
sort(_castToUint256Array(array), Comparators.lt);
return array;
}
/**
* @dev Sort an array of bytes32 (in memory) following the provided comparator function.
*
* This function does the sorting "in place", meaning that it overrides the input. The object is returned for
* convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
*
* NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
* array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
* when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
* consume more gas than is available in a block, leading to potential DoS.
*
* IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
*/
function sort(
bytes32[] memory array,
function(bytes32, bytes32) pure returns (bool) comp
) internal pure returns (bytes32[] memory) {
sort(_castToUint256Array(array), _castToUint256Comp(comp));
return array;
}
/**
* @dev Variant of {sort} that sorts an array of bytes32 in increasing order.
*/
function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {
sort(_castToUint256Array(array), Comparators.lt);
return array;
}
/**
* @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops
* at end (exclusive). Sorting follows the `comp` comparator.
*
* Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.
*
* IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should
* be used only if the limits are within a memory array.
*/
function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {
unchecked {
if (end - begin < 0x40) return;
// Use first element as pivot
uint256 pivot = _mload(begin);
// Position where the pivot should be at the end of the loop
uint256 pos = begin;
for (uint256 it = begin + 0x20; it < end; it += 0x20) {
if (comp(_mload(it), pivot)) {
// If the value stored at the iterator's position comes before the pivot, we increment the
// position of the pivot and move the value there.
pos += 0x20;
_swap(pos, it);
}
}
_swap(begin, pos); // Swap pivot into place
_quickSort(begin, pos, comp); // Sort the left side of the pivot
_quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot
}
}
/**
* @dev Pointer to the memory location of the first element of `array`.
*/
function _begin(uint256[] memory array) private pure returns (uint256 ptr) {
assembly ("memory-safe") {
ptr := add(array, 0x20)
}
}
/**
* @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word
* that comes just after the last element of the array.
*/
function _end(uint256[] memory array) private pure returns (uint256 ptr) {
unchecked {
return _begin(array) + array.length * 0x20;
}
}
/**
* @dev Load memory word (as a uint256) at location `ptr`.
*/
function _mload(uint256 ptr) private pure returns (uint256 value) {
assembly {
value := mload(ptr)
}
}
/**
* @dev Swaps the elements memory location `ptr1` and `ptr2`.
*/
function _swap(uint256 ptr1, uint256 ptr2) private pure {
assembly {
let value1 := mload(ptr1)
let value2 := mload(ptr2)
mstore(ptr1, value2)
mstore(ptr2, value1)
}
}
/// @dev Helper: low level cast address memory array to uint256 memory array
function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {
assembly {
output := input
}
}
/// @dev Helper: low level cast bytes32 memory array to uint256 memory array
function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {
assembly {
output := input
}
}
/// @dev Helper: low level cast address comp function to uint256 comp function
function _castToUint256Comp(
function(address, address) pure returns (bool) input
) private pure returns (function(uint256, uint256) pure returns (bool) output) {
assembly {
output := input
}
}
/// @dev Helper: low level cast bytes32 comp function to uint256 comp function
function _castToUint256Comp(
function(bytes32, bytes32) pure returns (bool) input
) private pure returns (function(uint256, uint256) pure returns (bool) output) {
assembly {
output := input
}
}
/**
* @dev Searches a sorted `array` and returns the first index that contains
* a value greater or equal to `element`. If no such index exists (i.e. all
* values in the array are strictly less than `element`), the array length is
* returned. Time complexity O(log n).
*
* NOTE: The `array` is expected to be sorted in ascending order, and to
* contain no repeated elements.
*
* IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks
* support for repeated elements in the array. The {lowerBound} function should
* be used instead.
*/
function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeAccess(array, mid).value > element) {
high = mid;
} else {
low = mid + 1;
}
}
// At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
if (low > 0 && unsafeAccess(array, low - 1).value == element) {
return low - 1;
} else {
return low;
}
}
/**
* @dev Searches an `array` sorted in ascending order and returns the first
* index that contains a value greater or equal than `element`. If no such index
* exists (i.e. all values in the array are strictly less than `element`), the array
* length is returned. Time complexity O(log n).
*
* See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].
*/
function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeAccess(array, mid).value < element) {
// this cannot overflow because mid < high
unchecked {
low = mid + 1;
}
} else {
high = mid;
}
}
return low;
}
/**
* @dev Searches an `array` sorted in ascending order and returns the first
* index that contains a value strictly greater than `element`. If no such index
* exists (i.e. all values in the array are strictly less than `element`), the array
* length is returned. Time complexity O(log n).
*
* See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].
*/
function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeAccess(array, mid).value > element) {
high = mid;
} else {
// this cannot overflow because mid < high
unchecked {
low = mid + 1;
}
}
}
return low;
}
/**
* @dev Same as {lowerBound}, but with an array in memory.
*/
function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeMemoryAccess(array, mid) < element) {
// this cannot overflow because mid < high
unchecked {
low = mid + 1;
}
} else {
high = mid;
}
}
return low;
}
/**
* @dev Same as {upperBound}, but with an array in memory.
*/
function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeMemoryAccess(array, mid) > element) {
high = mid;
} else {
// this cannot overflow because mid < high
unchecked {
low = mid + 1;
}
}
}
return low;
}
/**
* @dev Copies the content of `array`, from `start` (included) to the end of `array` into a new address array in
* memory.
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]
*/
function slice(address[] memory array, uint256 start) internal pure returns (address[] memory) {
return slice(array, start, array.length);
}
/**
* @dev Copies the content of `array`, from `start` (included) to `end` (excluded) into a new address array in
* memory. The `end` argument is truncated to the length of the `array`.
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]
*/
function slice(address[] memory array, uint256 start, uint256 end) internal pure returns (address[] memory) {
// sanitize
end = Math.min(end, array.length);
start = Math.min(start, end);
// allocate and copy
address[] memory result = new address[](end - start);
assembly ("memory-safe") {
mcopy(add(result, 0x20), add(add(array, 0x20), mul(start, 0x20)), mul(sub(end, start), 0x20))
}
return result;
}
/**
* @dev Copies the content of `array`, from `start` (included) to the end of `array` into a new bytes32 array in
* memory.
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]
*/
function slice(bytes32[] memory array, uint256 start) internal pure returns (bytes32[] memory) {
return slice(array, start, array.length);
}
/**
* @dev Copies the content of `array`, from `start` (included) to `end` (excluded) into a new bytes32 array in
* memory. The `end` argument is truncated to the length of the `array`.
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]
*/
function slice(bytes32[] memory array, uint256 start, uint256 end) internal pure returns (bytes32[] memory) {
// sanitize
end = Math.min(end, array.length);
start = Math.min(start, end);
// allocate and copy
bytes32[] memory result = new bytes32[](end - start);
assembly ("memory-safe") {
mcopy(add(result, 0x20), add(add(array, 0x20), mul(start, 0x20)), mul(sub(end, start), 0x20))
}
return result;
}
/**
* @dev Copies the content of `array`, from `start` (included) to the end of `array` into a new uint256 array in
* memory.
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]
*/
function slice(uint256[] memory array, uint256 start) internal pure returns (uint256[] memory) {
return slice(array, start, array.length);
}
/**
* @dev Copies the content of `array`, from `start` (included) to `end` (excluded) into a new uint256 array in
* memory. The `end` argument is truncated to the length of the `array`.
*
* NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]
*/
function slice(uint256[] memory array, uint256 start, uint256 end) internal pure returns (uint256[] memory) {
// sanitize
end = Math.min(end, array.length);
start = Math.min(start, end);
// allocate and copy
uint256[] memory result = new uint256[](end - start);
assembly ("memory-safe") {
mcopy(add(result, 0x20), add(add(array, 0x20), mul(start, 0x20)), mul(sub(end, start), 0x20))
}
return result;
}
/**
* @dev Moves the content of `array`, from `start` (included) to the end of `array` to the start of that array,
* and shrinks the array length accordingly, effectively overwriting the array with array[start:].
*
* NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead.
*/
function splice(address[] memory array, uint256 start) internal pure returns (address[] memory) {
return splice(array, start, array.length);
}
/**
* @dev Moves the content of `array`, from `start` (included) to `end` (excluded) to the start of that array,
* and shrinks the array length accordingly, effectively overwriting the array with array[start:end]. The
* `end` argument is truncated to the length of the `array`.
*
* NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead.
*/
function splice(address[] memory array, uint256 start, uint256 end) internal pure returns (address[] memory) {
// sanitize
end = Math.min(end, array.length);
start = Math.min(start, end);
// move and resize
assembly ("memory-safe") {
mcopy(add(array, 0x20), add(add(array, 0x20), mul(start, 0x20)), mul(sub(end, start), 0x20))
mstore(array, sub(end, start))
}
return array;
}
/**
* @dev Replaces elements in `array` starting at `pos` with all elements from `replacement`.
*
* Parameters are clamped to valid ranges (e.g. `pos` is clamped to `[0, array.length]`).
* If `pos >= array.length`, no replacement occurs and the array is returned unchanged.
*
* NOTE: This function modifies the provided array in place.
*/
function replace(
address[] memory array,
uint256 pos,
address[] memory replacement
) internal pure returns (address[] memory) {
return replace(array, pos, replacement, 0, replacement.length);
}
/**
* @dev Replaces elements in `array` starting at `pos` with elements from `replacement` starting at `offset`.
* Copies at most `length` elements from `replacement` to `array`.
*
* Parameters are clamped to valid ranges (i.e. `pos` is clamped to `[0, array.length]`, `offset` is
* clamped to `[0, replacement.length]`, and `length` is clamped to `min(length, replacement.length - offset,
* array.length - pos)`). If `pos >= array.length` or `offset >= replacement.length`, no replacement occurs
* and the array is returned unchanged.
*
* NOTE: This function modifies the provided array in place.
*/
function replace(
address[] memory array,
uint256 pos,
address[] memory replacement,
uint256 offset,
uint256 length
) internal pure returns (address[] memory) {
// sanitize
pos = Math.min(pos, array.length);
offset = Math.min(offset, replacement.length);
length = Math.min(length, Math.min(replacement.length - offset, array.length - pos));
// replace
assembly ("memory-safe") {
mcopy(
add(add(array, 0x20), mul(pos, 0x20)),
add(add(replacement, 0x20), mul(offset, 0x20)),
mul(length, 0x20)
)
}
return array;
}
/**
* @dev Moves the content of `array`, from `start` (included) to the end of `array` to the start of that array,
* and shrinks the array length accordingly, effectively overwriting the array with array[start:].
*
* NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead.
*/
function splice(bytes32[] memory array, uint256 start) internal pure returns (bytes32[] memory) {
return splice(array, start, array.length);
}
/**
* @dev Moves the content of `array`, from `start` (included) to `end` (excluded) to the start of that array,
* and shrinks the array length accordingly, effectively overwriting the array with array[start:end]. The
* `end` argument is truncated to the length of the `array`.
*
* NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead.
*/
function splice(bytes32[] memory array, uint256 start, uint256 end) internal pure returns (bytes32[] memory) {
// sanitize
end = Math.min(end, array.length);
start = Math.min(start, end);
// move and resize
assembly ("memory-safe") {
mcopy(add(array, 0x20), add(add(array, 0x20), mul(start, 0x20)), mul(sub(end, start), 0x20))
mstore(array, sub(end, start))
}
return array;
}
/**
* @dev Replaces elements in `array` starting at `pos` with all elements from `replacement`.
*
* Parameters are clamped to valid ranges (e.g. `pos` is clamped to `[0, array.length]`).
* If `pos >= array.length`, no replacement occurs and the array is returned unchanged.
*
* NOTE: This function modifies the provided array in place.
*/
function replace(
bytes32[] memory array,
uint256 pos,
bytes32[] memory replacement
) internal pure returns (bytes32[] memory) {
return replace(array, pos, replacement, 0, replacement.length);
}
/**
* @dev Replaces elements in `array` starting at `pos` with elements from `replacement` starting at `offset`.
* Copies at most `length` elements from `replacement` to `array`.
*
* Parameters are clamped to valid ranges (i.e. `pos` is clamped to `[0, array.length]`, `offset` is
* clamped to `[0, replacement.length]`, and `length` is clamped to `min(length, replacement.length - offset,
* array.length - pos)`). If `pos >= array.length` or `offset >= replacement.length`, no replacement occurs
* and the array is returned unchanged.
*
* NOTE: This function modifies the provided array in place.
*/
function replace(
bytes32[] memory array,
uint256 pos,
bytes32[] memory replacement,
uint256 offset,
uint256 length
) internal pure returns (bytes32[] memory) {
// sanitize
pos = Math.min(pos, array.length);
offset = Math.min(offset, replacement.length);
length = Math.min(length, Math.min(replacement.length - offset, array.length - pos));
// replace
assembly ("memory-safe") {
mcopy(
add(add(array, 0x20), mul(pos, 0x20)),
add(add(replacement, 0x20), mul(offset, 0x20)),
mul(length, 0x20)
)
}
return array;
}
/**
* @dev Moves the content of `array`, from `start` (included) to the end of `array` to the start of that array,
* and shrinks the array length accordingly, effectively overwriting the array with array[start:].
*
* NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead.
*/
function splice(uint256[] memory array, uint256 start) internal pure returns (uint256[] memory) {
return splice(array, start, array.length);
}
/**
* @dev Moves the content of `array`, from `start` (included) to `end` (excluded) to the start of that array,
* and shrinks the array length accordingly, effectively overwriting the array with array[start:end]. The
* `end` argument is truncated to the length of the `array`.
*
* NOTE: This function modifies the provided array in place. If you need to preserve the original array, use {slice} instead.
*/
function splice(uint256[] memory array, uint256 start, uint256 end) internal pure returns (uint256[] memory) {
// sanitize
end = Math.min(end, array.length);
start = Math.min(start, end);
// move and resize
assembly ("memory-safe") {
mcopy(add(array, 0x20), add(add(array, 0x20), mul(start, 0x20)), mul(sub(end, start), 0x20))
mstore(array, sub(end, start))
}
return array;
}
/**
* @dev Replaces elements in `array` starting at `pos` with all elements from `replacement`.
*
* Parameters are clamped to valid ranges (e.g. `pos` is clamped to `[0, array.length]`).
* If `pos >= array.length`, no replacement occurs and the array is returned unchanged.
*
* NOTE: This function modifies the provided array in place.
*/
function replace(
uint256[] memory array,
uint256 pos,
uint256[] memory replacement
) internal pure returns (uint256[] memory) {
return replace(array, pos, replacement, 0, replacement.length);
}
/**
* @dev Replaces elements in `array` starting at `pos` with elements from `replacement` starting at `offset`.
* Copies at most `length` elements from `replacement` to `array`.
*
* Parameters are clamped to valid ranges (i.e. `pos` is clamped to `[0, array.length]`, `offset` is
* clamped to `[0, replacement.length]`, and `length` is clamped to `min(length, replacement.length - offset,
* array.length - pos)`). If `pos >= array.length` or `offset >= replacement.length`, no replacement occurs
* and the array is returned unchanged.
*
* NOTE: This function modifies the provided array in place.
*/
function replace(
uint256[] memory array,
uint256 pos,
uint256[] memory replacement,
uint256 offset,
uint256 length
) internal pure returns (uint256[] memory) {
// sanitize
pos = Math.min(pos, array.length);
offset = Math.min(offset, replacement.length);
length = Math.min(length, Math.min(replacement.length - offset, array.length - pos));
// replace
assembly ("memory-safe") {
mcopy(
add(add(array, 0x20), mul(pos, 0x20)),
add(add(replacement, 0x20), mul(offset, 0x20)),
mul(length, 0x20)
)
}
return array;
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
bytes32 slot;
assembly ("memory-safe") {
slot := arr.slot
}
return slot.deriveArray().offset(pos).getAddressSlot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
bytes32 slot;
assembly ("memory-safe") {
slot := arr.slot
}
return slot.deriveArray().offset(pos).getBytes32Slot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
bytes32 slot;
assembly ("memory-safe") {
slot := arr.slot
}
return slot.deriveArray().offset(pos).getUint256Slot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(bytes[] storage arr, uint256 pos) internal pure returns (StorageSlot.BytesSlot storage) {
bytes32 slot;
assembly ("memory-safe") {
slot := arr.slot
}
return slot.deriveArray().offset(pos).getBytesSlot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(string[] storage arr, uint256 pos) internal pure returns (StorageSlot.StringSlot storage) {
bytes32 slot;
assembly ("memory-safe") {
slot := arr.slot
}
return slot.deriveArray().offset(pos).getStringSlot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(bytes[] memory arr, uint256 pos) internal pure returns (bytes memory res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(string[] memory arr, uint256 pos) internal pure returns (string memory res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, or initialize elements if length is increased.
*/
function unsafeSetLength(address[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, or initialize elements if length is increased.
*/
function unsafeSetLength(bytes32[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, or initialize elements if length is increased.
*/
function unsafeSetLength(uint256[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, or initialize elements if length is increased.
*/
function unsafeSetLength(bytes[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, or initialize elements if length is increased.
*/
function unsafeSetLength(string[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
}
// File: @openzeppelin/contracts/token/ERC1155/ERC1155.sol
// OpenZeppelin Contracts (last updated v5.6.0) (token/ERC1155/ERC1155.sol)
pragma solidity ^0.8.24;
/**
* @dev Implementation of the basic standard multi-token.
* See https://eips.ethereum.org/EIPS/eip-1155
* Originally based on code by Enjin: https://github.com/enjin/erc-1155
*/
abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors {
using Arrays for uint256[];
using Arrays for address[];
mapping(uint256 id => mapping(address account => uint256)) private _balances;
mapping(address account => mapping(address operator => bool)) private _operatorApprovals;
// Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
string private _uri;
/**
* @dev See {_setURI}.
*/
constructor(string memory uri_) {
_setURI(uri_);
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC1155).interfaceId ||
interfaceId == type(IERC1155MetadataURI).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC1155MetadataURI-uri}.
*
* This implementation returns the same URI for *all* token types. It relies
* on the token type ID substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the ERC].
*
* Clients calling this function must replace the `\{id\}` substring with the
* actual token type ID.
*/
function uri(uint256 /* id */) public view virtual returns (string memory) {
return _uri;
}
/// @inheritdoc IERC1155
function balanceOf(address account, uint256 id) public view virtual returns (uint256) {
return _balances[id][account];
}
/**
* @dev See {IERC1155-balanceOfBatch}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(
address[] memory accounts,
uint256[] memory ids
) public view virtual returns (uint256[] memory) {
if (accounts.length != ids.length) {
revert ERC1155InvalidArrayLength(ids.length, accounts.length);
}
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));
}
return batchBalances;
}
/// @inheritdoc IERC1155
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/// @inheritdoc IERC1155
function isApprovedForAll(address account, address operator) public view virtual returns (bool) {
return _operatorApprovals[account][operator];
}
/// @inheritdoc IERC1155
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual {
_checkAuthorized(_msgSender(), from);
_safeTransferFrom(from, to, id, value, data);
}
/// @inheritdoc IERC1155
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) public virtual {
_checkAuthorized(_msgSender(), from);
_safeBatchTransferFrom(from, to, ids, values, data);
}
/// @dev Checks if `operator` is authorized to transfer tokens owned by `owner`. Reverts with {ERC1155MissingApprovalForAll} if not.
function _checkAuthorized(address operator, address owner) internal view virtual {
if (owner != operator && !isApprovedForAll(owner, operator)) {
revert ERC1155MissingApprovalForAll(operator, owner);
}
}
/**
* @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from`
* (or `to`) is the zero address.
*
* Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received}
* or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value.
* - `ids` and `values` must have the same length.
*
* NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead.
*/
function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual {
if (ids.length != values.length) {
revert ERC1155InvalidArrayLength(ids.length, values.length);
}
address operator = _msgSender();
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids.unsafeMemoryAccess(i);
uint256 value = values.unsafeMemoryAccess(i);
if (from != address(0)) {
uint256 fromBalance = _balances[id][from];
if (fromBalance < value) {
revert ERC1155InsufficientBalance(from, fromBalance, value, id);
}
unchecked {
// Overflow not possible: value <= fromBalance
_balances[id][from] = fromBalance - value;
}
}
if (to != address(0)) {
_balances[id][to] += value;
}
}
if (ids.length == 1) {
uint256 id = ids.unsafeMemoryAccess(0);
uint256 value = values.unsafeMemoryAccess(0);
emit TransferSingle(operator, from, to, id, value);
} else {
emit TransferBatch(operator, from, to, ids, values);
}
}
/**
* @dev Version of {_update} that performs the token acceptance check by calling
* {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it
* contains code (eg. is a smart contract at the moment of execution).
*
* IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any
* update to the contract state after this function would break the check-effect-interaction pattern. Consider
* overriding {_update} instead.
*
* NOTE: This version is kept for backward compatibility. We recommend calling the alternative version with a boolean
* flag in order to achieve better control over which hook to call.
*/
function _updateWithAcceptanceCheck(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal virtual {
_updateWithAcceptanceCheck(from, to, ids, values, data, ids.length != 1);
}
/**
* @dev Version of {_update} that performs the token acceptance check by calling
* {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it
* contains code (eg. is a smart contract at the moment of execution).
*
* IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any
* update to the contract state after this function would break the check-effect-interaction pattern. Consider
* overriding {_update} instead.
*/
function _updateWithAcceptanceCheck(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data,
bool batch
) internal virtual {
_update(from, to, ids, values);
if (to != address(0)) {
address operator = _msgSender();
if (batch) {
ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data);
} else {
uint256 id = ids.unsafeMemoryAccess(0);
uint256 value = values.unsafeMemoryAccess(0);
ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data);
}
}
}
/**
* @dev Transfers a `value` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `from` must have a balance of tokens of type `id` of at least `value` amount.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(from, to, ids, values, data, false);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
* - `ids` and `values` must have the same length.
*/
function _safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
_updateWithAcceptanceCheck(from, to, ids, values, data, true);
}
/**
* @dev Sets a new URI for all token types, by relying on the token type ID
* substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the ERC].
*
* By this mechanism, any occurrence of the `\{id\}` substring in either the
* URI or any of the values in the JSON file at said URI will be replaced by
* clients with the token type ID.
*
* For example, the `https://token-cdn-domain/\{id\}.json` URI would be
* interpreted by clients as
* `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
* for token type ID 0x4cce0.
*
* See {uri}.
*
* Because these URIs cannot be meaningfully represented by the {URI} event,
* this function emits no events.
*/
function _setURI(string memory newuri) internal virtual {
_uri = newuri;
}
/**
* @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(address(0), to, ids, values, data, false);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `values` must have the same length.
* - `to` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal {
if (to == address(0)) {
revert ERC1155InvalidReceiver(address(0));
}
_updateWithAcceptanceCheck(address(0), to, ids, values, data, true);
}
/**
* @dev Destroys a `value` amount of tokens of type `id` from `from`
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `from` must have at least `value` amount of tokens of type `id`.
*/
function _burn(address from, uint256 id, uint256 value) internal {
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
(uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
_updateWithAcceptanceCheck(from, address(0), ids, values, "", false);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `from` must have at least `value` amount of tokens of type `id`.
* - `ids` and `values` must have the same length.
*/
function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal {
if (from == address(0)) {
revert ERC1155InvalidSender(address(0));
}
_updateWithAcceptanceCheck(from, address(0), ids, values, "", true);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `operator` cannot be the zero address.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (owner == address(0)) {
revert ERC1155InvalidApprover(address(0));
}
if (operator == address(0)) {
revert ERC1155InvalidOperator(address(0));
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Creates an array in memory with only one value for each of the elements provided.
*/
function _asSingletonArrays(
uint256 element1,
uint256 element2
) private pure returns (uint256[] memory array1, uint256[] memory array2) {
assembly ("memory-safe") {
// Load the free memory pointer
array1 := mload(0x40)
// Set array length to 1
mstore(array1, 1)
// Store the single element at the next word after the length (where content starts)
mstore(add(array1, 0x20), element1)
// Repeat for next array locating it right after the first array
array2 := add(array1, 0x40)
mstore(array2, 1)
mstore(add(array2, 0x20), element2)
// Update the free memory pointer by pointing after the second array
mstore(0x40, add(array2, 0x40))
}
}
}
// File: @openzeppelin/contracts/access/Ownable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File: @openzeppelin/contracts/security/Pausable.sol
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
/**
* @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 {
/**
* @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);
bool private _paused;
/**
* @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 {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @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/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
// File: @openzeppelin/contracts/interfaces/IERC20.sol
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
// File: @openzeppelin/contracts/interfaces/IERC165.sol
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
// File: @openzeppelin/contracts/interfaces/IERC1363.sol
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}
// File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
if (!_safeTransfer(token, to, value, true)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
if (!_safeTransferFrom(token, from, to, value, true)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _safeTransfer(token, to, value, false);
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _safeTransferFrom(token, from, to, value, false);
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
if (!_safeApprove(token, spender, value, false)) {
if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));
if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Oppositely, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the
* return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param to The recipient of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {
bytes4 selector = IERC20.transfer.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(to, shr(96, not(0))))
mstore(0x24, value)
success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
}
}
/**
* @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return
* value: the return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param from The sender of the tokens
* @param to The recipient of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value,
bool bubble
) private returns (bool success) {
bytes4 selector = IERC20.transferFrom.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(from, shr(96, not(0))))
mstore(0x24, and(to, shr(96, not(0))))
mstore(0x44, value)
success := call(gas(), token, 0, 0x00, 0x64, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
mstore(0x60, 0)
}
}
/**
* @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:
* the return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param spender The spender of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {
bytes4 selector = IERC20.approve.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(spender, shr(96, not(0))))
mstore(0x24, value)
success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
}
}
}
// File: @openzeppelin/contracts/security/ReentrancyGuard.sol
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
// File: @openzeppelin/contracts/interfaces/IERC2981.sol
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC2981.sol)
pragma solidity >=0.6.2;
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*/
interface IERC2981 is IERC165 {
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*
* NOTE: ERC-2981 allows setting the royalty to 100% of the price. In that case all the price would be sent to the
* royalty receiver and 0 tokens to the seller. Contracts dealing with royalty should consider empty transfers.
*/
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) external view returns (address receiver, uint256 royaltyAmount);
}
// File: @openzeppelin/contracts/token/common/ERC2981.sol
// OpenZeppelin Contracts (last updated v5.4.0) (token/common/ERC2981.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
*
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
* fee is specified in basis points by default.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the ERC. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*/
abstract contract ERC2981 is IERC2981, ERC165 {
struct RoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo;
/**
* @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).
*/
error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);
/**
* @dev The default royalty receiver is invalid.
*/
error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);
/**
* @dev The royalty set for a specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
*/
error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);
/**
* @dev The royalty receiver for `tokenId` is invalid.
*/
error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
}
/// @inheritdoc IERC2981
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) public view virtual returns (address receiver, uint256 amount) {
RoyaltyInfo storage _royaltyInfo = _tokenRoyaltyInfo[tokenId];
address royaltyReceiver = _royaltyInfo.receiver;
uint96 royaltyFraction = _royaltyInfo.royaltyFraction;
if (royaltyReceiver == address(0)) {
royaltyReceiver = _defaultRoyaltyInfo.receiver;
royaltyFraction = _defaultRoyaltyInfo.royaltyFraction;
}
uint256 royaltyAmount = (salePrice * royaltyFraction) / _feeDenominator();
return (royaltyReceiver, royaltyAmount);
}
/**
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
* override.
*/
function _feeDenominator() internal pure virtual returns (uint96) {
return 10000;
}
/**
* @dev Sets the royalty information that all ids in this contract will default to.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale price
revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);
}
if (receiver == address(0)) {
revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));
}
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/
function _deleteDefaultRoyalty() internal virtual {
delete _defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale price
revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);
}
if (receiver == address(0)) {
revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));
}
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/
function _resetTokenRoyalty(uint256 tokenId) internal virtual {
delete _tokenRoyaltyInfo[tokenId];
}
}
// File: contracts/AureonPrime.sol
pragma solidity ^0.8.24;
contract AureonPrimeNFT is ERC1155, ERC2981, Ownable, Pausable, ReentrancyGuard {
using SafeERC20 for IERC20;
string public name = "Aureon Prime NFT";
string public symbol = "AUPR";
uint256 public constant MAX_TYPE = 16;
uint256 public constant RESET_TIME = 21 days;
uint256 public constant MAX_FREE_MINT = 1;
uint256 public constant MAX_PAID_MINT = 2;
uint256 public constant MAX_TX = 3;
struct NftType {
uint256 maxSupply;
uint256 minted;
bool active;
}
mapping(uint256 => NftType) public nftTypes;
mapping(uint256 => string) private tokenUris;
mapping(address => bool) public allowedPaymentTokens;
mapping(uint256 => mapping(address => uint256)) public typeTokenPrice;
mapping(address => mapping(uint256 => uint256)) public freeMintCountPerId;
mapping(address => mapping(uint256 => uint256)) public paidMintCountPerId;
mapping(address => uint256) public lastMintReset;
mapping(address => bool) public whitelist;
bool public whitelistActive = false;
event Minted(
address indexed user,
uint256 indexed id,
uint256 amount,
address indexed paymentToken,
uint256 totalPaid
);
event SupplyIncreased(uint256 indexed id, uint256 addedSupply);
event TypeUpdated(uint256 indexed id, uint256 maxSupply, bool active);
event UriUpdated(uint256 indexed id, string newUri);
event PaymentTokenUpdated(address indexed token, bool allowed);
event TypeTokenPriceUpdated(uint256 indexed id, address indexed token, uint256 price);
event WhitelistUpdated(address indexed user, bool allowed);
event RoyaltyUpdated(address indexed receiver, uint96 fee);
constructor() ERC1155("") Ownable(msg.sender) {
_setDefaultRoyalty(msg.sender, 500); // %5 royalty
nftTypes[1] = NftType(1500,0,true);
nftTypes[2] = NftType(1000,0,true);
nftTypes[3] = NftType(900,0,true);
nftTypes[4] = NftType(800,0,true);
nftTypes[5] = NftType(600,0,true);
nftTypes[6] = NftType(500,0,true);
nftTypes[7] = NftType(400,0,true);
nftTypes[8] = NftType(300,0,true);
nftTypes[9] = NftType(250,0,true);
nftTypes[10] = NftType(100,0,true);
nftTypes[11] = NftType(150,0,true);
nftTypes[12] = NftType(120,0,true);
nftTypes[13] = NftType(100,0,true);
nftTypes[14] = NftType(80,0,true);
nftTypes[15] = NftType(60,0,true);
nftTypes[16] = NftType(40,0,true);
}
// ADMIN
function setType(uint256 id,uint256 maxSupply,bool active) external onlyOwner {
require(id >=1 && id <= MAX_TYPE,"Invalid type");
require(maxSupply >= nftTypes[id].minted,"Below minted");
nftTypes[id].maxSupply = maxSupply;
nftTypes[id].active = active;
emit TypeUpdated(id,maxSupply,active);
}
function increaseSupply(uint256 id,uint256 addedSupply) external onlyOwner {
require(id >=1 && id <= MAX_TYPE,"Invalid type");
require(addedSupply >0,"Invalid supply");
nftTypes[id].maxSupply += addedSupply;
emit SupplyIncreased(id,addedSupply);
}
function setTokenUri(uint256 id,string calldata newUri) external onlyOwner {
require(id >=1 && id <= MAX_TYPE,"Invalid type");
tokenUris[id] = newUri;
emit UriUpdated(id,newUri);
}
function setPaymentToken(address token,bool allowed) external onlyOwner {
require(token != address(0),"Zero address");
allowedPaymentTokens[token] = allowed;
emit PaymentTokenUpdated(token,allowed);
}
function setTypeTokenPrice(uint256 id,address token,uint256 price) external onlyOwner {
require(id >=1 && id <= MAX_TYPE,"Invalid type");
require(allowedPaymentTokens[token],"Token not allowed");
typeTokenPrice[id][token] = price;
emit TypeTokenPriceUpdated(id,token,price);
}
function pause() external onlyOwner { _pause(); }
function unpause() external onlyOwner { _unpause(); }
function setRoyalty(address receiver,uint96 fee) external onlyOwner {
_setDefaultRoyalty(receiver,fee);
emit RoyaltyUpdated(receiver,fee);
}
function withdrawToken(address token,address to) external onlyOwner {
uint256 balance = IERC20(token).balanceOf(address(this));
IERC20(token).safeTransfer(to,balance);
}
function addToWhitelist(address user,bool allowed) external onlyOwner {
whitelist[user] = allowed;
emit WhitelistUpdated(user,allowed);
}
function setWhitelistActive(bool active) external onlyOwner {
whitelistActive = active;
}
// USER
function mintWithToken(uint256 id,uint256 amount,address paymentToken)
external
whenNotPaused
nonReentrant
{
require(id >=1 && id <= MAX_TYPE,"Invalid type");
require(amount >0 && amount <= MAX_TX,"Invalid amount");
require(allowedPaymentTokens[paymentToken],"Token not allowed");
NftType storage nft = nftTypes[id];
require(nft.active,"Type inactive");
require(nft.minted + amount <= nft.maxSupply,"Sold out");
if(whitelistActive){
require(whitelist[msg.sender],"Not whitelisted");
}
if(lastMintReset[msg.sender] == 0 || block.timestamp > lastMintReset[msg.sender] + RESET_TIME){
for(uint256 i = 1; i <= MAX_TYPE; i++) {
freeMintCountPerId[msg.sender][i] = 0;
paidMintCountPerId[msg.sender][i] = 0;
}
lastMintReset[msg.sender] = block.timestamp;
}
uint256 unitPrice = typeTokenPrice[id][paymentToken];
uint256 totalPrice = unitPrice * amount;
if(unitPrice == 0){
require(
freeMintCountPerId[msg.sender][id] + amount <= MAX_FREE_MINT,
"Free mint limit"
);
freeMintCountPerId[msg.sender][id] += amount;
} else {
require(
paidMintCountPerId[msg.sender][id] + amount <= MAX_PAID_MINT,
"Paid mint limit"
);
paidMintCountPerId[msg.sender][id] += amount;
IERC20(paymentToken).safeTransferFrom(msg.sender,address(this),totalPrice);
}
nft.minted += amount;
_mint(msg.sender,id,amount,"");
emit Minted(msg.sender,id,amount,paymentToken,totalPrice);
}
// VIEW
function uri(uint256 id) public view override returns(string memory){
require(id >=1 && id <= MAX_TYPE,"Invalid type");
return tokenUris[id];
}
function getType(uint256 id)
external
view
returns(uint256 maxSupply,uint256 minted,bool active,uint256 remaining)
{
NftType memory nft = nftTypes[id];
return(
nft.maxSupply,
nft.minted,
nft.active,
nft.maxSupply - nft.minted
);
}
function getPrice(uint256 id,address token) external view returns(uint256){
return typeTokenPrice[id][token];
}
function userMintInfo(address user,uint256 id)
external
view
returns(uint256 freeMinted,uint256 paidMinted)
{
return(
freeMintCountPerId[user][id],
paidMintCountPerId[user][id]
);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC1155,ERC2981)
returns(bool)
{
return super.supportsInterface(interfaceId);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"paymentToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalPaid","type":"uint256"}],"name":"Minted","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":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"PaymentTokenUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"fee","type":"uint96"}],"name":"RoyaltyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"addedSupply","type":"uint256"}],"name":"SupplyIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"TypeTokenPriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxSupply","type":"uint256"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"TypeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"string","name":"newUri","type":"string"}],"name":"UriUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"WhitelistUpdated","type":"event"},{"inputs":[],"name":"MAX_FREE_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PAID_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TYPE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESET_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"addToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowedPaymentTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"freeMintCountPerId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getType","outputs":[{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"minted","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"remaining","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"addedSupply","type":"uint256"}],"name":"increaseSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastMintReset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"paymentToken","type":"address"}],"name":"mintWithToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nftTypes","outputs":[{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"minted","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"paidMintCountPerId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","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":"address","name":"token","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setPaymentToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"fee","type":"uint96"}],"name":"setRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"newUri","type":"string"}],"name":"setTokenUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"name":"setType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"setTypeTokenPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"active","type":"bool"}],"name":"setWhitelistActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"typeTokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"userMintInfo","outputs":[{"internalType":"uint256","name":"freeMinted","type":"uint256"},{"internalType":"uint256","name":"paidMinted","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040526040518060400160405280601081526020017f417572656f6e205072696d65204e465400000000000000000000000000000000815250600790816100489190610cb2565b506040518060400160405280600481526020017f41555052000000000000000000000000000000000000000000000000000000008152506008908161008d9190610cb2565b505f60115f6101000a81548160ff0219169083151502179055503480156100b2575f5ffd5b503360405180602001604052805f8152506100d2816107e460201b60201c565b505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610143575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161013a9190610dc0565b60405180910390fd5b610152816107f760201b60201c565b505f600560146101000a81548160ff0219169083151502179055506001600681905550610187336101f46108ba60201b60201c565b60405180606001604052806105dc81526020015f81526020016001151581525060095f600181526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff02191690831515021790555090505060405180606001604052806103e881526020015f81526020016001151581525060095f600281526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff021916908315150217905550905050604051806060016040528061038481526020015f81526020016001151581525060095f600381526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff021916908315150217905550905050604051806060016040528061032081526020015f81526020016001151581525060095f600481526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff021916908315150217905550905050604051806060016040528061025881526020015f81526020016001151581525060095f600581526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff02191690831515021790555090505060405180606001604052806101f481526020015f81526020016001151581525060095f600681526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff021916908315150217905550905050604051806060016040528061019081526020015f81526020016001151581525060095f600781526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff021916908315150217905550905050604051806060016040528061012c81526020015f81526020016001151581525060095f600881526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff021916908315150217905550905050604051806060016040528060fa81526020015f81526020016001151581525060095f600981526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff0219169083151502179055509050506040518060600160405280606481526020015f81526020016001151581525060095f600a81526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff0219169083151502179055509050506040518060600160405280609681526020015f81526020016001151581525060095f600b81526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff0219169083151502179055509050506040518060600160405280607881526020015f81526020016001151581525060095f600c81526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff0219169083151502179055509050506040518060600160405280606481526020015f81526020016001151581525060095f600d81526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff0219169083151502179055509050506040518060600160405280605081526020015f81526020016001151581525060095f600e81526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff0219169083151502179055509050506040518060600160405280603c81526020015f81526020016001151581525060095f600f81526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff0219169083151502179055509050506040518060600160405280602881526020015f81526020016001151581525060095f601081526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548160ff021916908315150217905550905050610e56565b80600290816107f39190610cb2565b5050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f6108c9610a5b60201b60201c565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff16111561092e5781816040517f6f483d09000000000000000000000000000000000000000000000000000000008152600401610925929190610e2f565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361099e575f6040517fb6d9900a0000000000000000000000000000000000000000000000000000000081526004016109959190610dc0565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff1681525060035f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f612710905090565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610adf57607f821691505b602082108103610af257610af1610a9b565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302610b547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610b19565b610b5e8683610b19565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f610ba2610b9d610b9884610b76565b610b7f565b610b76565b9050919050565b5f819050919050565b610bbb83610b88565b610bcf610bc782610ba9565b848454610b25565b825550505050565b5f5f905090565b610be6610bd7565b610bf1818484610bb2565b505050565b5f5b82811015610c1757610c0c5f828401610bde565b600181019050610bf8565b505050565b601f821115610c6a5782821115610c6957610c3681610af8565b610c3f83610b0a565b610c4885610b0a565b6020861015610c55575f90505b808301610c6482840382610bf6565b505050505b5b505050565b5f82821c905092915050565b5f610c8a5f1984600802610c6f565b1980831691505092915050565b5f610ca28383610c7b565b9150826002028217905092915050565b610cbb82610a64565b67ffffffffffffffff811115610cd457610cd3610a6e565b5b610cde8254610ac8565b610ce9828285610c1c565b5f60209050601f831160018114610d1a575f8415610d08578287015190505b610d128582610c97565b865550610d79565b601f198416610d2886610af8565b5f5b82811015610d4f57848901518255600182019150602085019450602081019050610d2a565b86831015610d6c5784890151610d68601f891682610c7b565b8355505b6001600288020188555050505b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610daa82610d81565b9050919050565b610dba81610da0565b82525050565b5f602082019050610dd35f830184610db1565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b5f610e0a610e05610e0084610dd9565b610b7f565b610b76565b9050919050565b610e1a81610df0565b82525050565b610e2981610b76565b82525050565b5f604082019050610e425f830185610e11565b610e4f6020830184610e20565b9392505050565b614eee80610e635f395ff3fe608060405234801561000f575f5ffd5b5060043610610266575f3560e01c806379b2ab231161014f578063a9cdb8e1116100c1578063d9b39a1111610085578063d9b39a1114610783578063e985e9c5146107a1578063e9e7e599146107d1578063f242432a146107ed578063f2fde38b14610809578063f3b2db3f1461082557610266565b8063a9cdb8e1146106e1578063bc93233f146106fd578063c3b754dc14610719578063c9846d7014610735578063d9197c321461076557610266565b80638da5cb5b116101135780638da5cb5b146106215780638f2fc60b1461063f57806395d89b411461065b5780639b19251a14610679578063a200635b146106a9578063a22cb465146106c557610266565b806379b2ab23146105665780637af44c7f146105985780637dd0fd19146105c85780637de9376b146105e65780638456cb591461061757610266565b80633f4ba83a116101e8578063430884cf116101ac578063430884cf146104a65780634e1273f4146104c257806357f7789e146104f25780635c975abb1461050e578063697d312a1461052c578063715018a61461055c57610266565b80633f4ba83a146103ff5780634036ab781461040957806340e43ec61461043c57806341c6dead1461046c57806341cda2031461048857610266565b80631881d72c1161022f5780631881d72c146103365780632a55205a146103665780632b57cfbb146103975780632eb2c2d6146103c75780633aeac4e1146103e357610266565b8062fdd58e1461026a57806301ffc9a71461029a57806302ce5813146102ca57806306fdde03146102e85780630e89341c14610306575b5f5ffd5b610284600480360381019061027f91906135a3565b610843565b60405161029191906135f0565b60405180910390f35b6102b460048036038101906102af919061365e565b610898565b6040516102c191906136a3565b60405180910390f35b6102d26108a9565b6040516102df91906136a3565b60405180910390f35b6102f06108bb565b6040516102fd919061372c565b60405180910390f35b610320600480360381019061031b919061374c565b610947565b60405161032d919061372c565b60405180910390f35b610350600480360381019061034b9190613777565b610a39565b60405161035d91906135f0565b60405180910390f35b610380600480360381019061037b91906137b5565b610a59565b60405161038e929190613802565b60405180910390f35b6103b160048036038101906103ac9190613777565b610b7b565b6040516103be91906135f0565b60405180910390f35b6103e160048036038101906103dc9190613a19565b610bd1565b005b6103fd60048036038101906103f89190613ae4565b610bf6565b005b610407610ca9565b005b610423600480360381019061041e919061374c565b610cbb565b6040516104339493929190613b22565b60405180910390f35b610456600480360381019061045191906135a3565b610d3c565b60405161046391906135f0565b60405180910390f35b61048660048036038101906104819190613b65565b610d5c565b005b6104906114cc565b60405161049d91906135f0565b60405180910390f35b6104c060048036038101906104bb9190613bdf565b6114d1565b005b6104dc60048036038101906104d79190613cdd565b6115ed565b6040516104e99190613e0a565b60405180910390f35b61050c60048036038101906105079190613e83565b6116f7565b005b6105166117b0565b60405161052391906136a3565b60405180910390f35b61054660048036038101906105419190613ee0565b6117c6565b60405161055391906136a3565b60405180910390f35b6105646117e3565b005b610580600480360381019061057b919061374c565b6117f6565b60405161058f93929190613f0b565b60405180910390f35b6105b260048036038101906105ad9190613ee0565b611828565b6040516105bf91906135f0565b60405180910390f35b6105d061183d565b6040516105dd91906135f0565b60405180910390f35b61060060048036038101906105fb91906135a3565b611844565b60405161060e929190613f40565b60405180910390f35b61061f6118eb565b005b6106296118fd565b6040516106369190613f67565b60405180910390f35b61065960048036038101906106549190613fc1565b611925565b005b610663611989565b604051610670919061372c565b60405180910390f35b610693600480360381019061068e9190613ee0565b611a15565b6040516106a091906136a3565b60405180910390f35b6106c360048036038101906106be9190613fff565b611a32565b005b6106df60048036038101906106da9190613bdf565b611bb9565b005b6106fb60048036038101906106f6919061404f565b611bcf565b005b61071760048036038101906107129190613bdf565b611d01565b005b610733600480360381019061072e919061409f565b611daf565b005b61074f600480360381019061074a91906135a3565b611dd3565b60405161075c91906135f0565b60405180910390f35b61076d611df3565b60405161077a91906135f0565b60405180910390f35b61078b611df8565b60405161079891906135f0565b60405180910390f35b6107bb60048036038101906107b69190613ae4565b611dfd565b6040516107c891906136a3565b60405180910390f35b6107eb60048036038101906107e691906137b5565b611e8b565b005b610807600480360381019061080291906140ca565b611f8b565b005b610823600480360381019061081e9190613ee0565b611fb0565b005b61082d612034565b60405161083a91906135f0565b60405180910390f35b5f5f5f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f6108a282612039565b9050919050565b60115f9054906101000a900460ff1681565b600780546108c89061418a565b80601f01602080910402602001604051908101604052809291908181526020018280546108f49061418a565b801561093f5780601f106109165761010080835404028352916020019161093f565b820191905f5260205f20905b81548152906001019060200180831161092257829003601f168201915b505050505081565b60606001821015801561095b575060108211155b61099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099190614204565b60405180910390fd5b600a5f8381526020019081526020015f2080546109b69061418a565b80601f01602080910402602001604051908101604052809291908181526020018280546109e29061418a565b8015610a2d5780601f10610a0457610100808354040283529160200191610a2d565b820191905f5260205f20905b815481529060010190602001808311610a1057829003601f168201915b50505050509050919050565b600c602052815f5260405f20602052805f5260405f205f91509150505481565b5f5f5f60045f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610b2d5760035f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915060035f0160149054906101000a90046bffffffffffffffffffffffff1690505b5f610b366120b2565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff1688610b5e919061424f565b610b6891906142bd565b9050828195509550505050509250929050565b5f600c5f8481526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b610be2610bdc6120bb565b866120c2565b610bef858585858561214d565b5050505050565b610bfe612243565b5f8273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c389190613f67565b602060405180830381865afa158015610c53573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c779190614301565b9050610ca482828573ffffffffffffffffffffffffffffffffffffffff166122ca9092919063ffffffff16565b505050565b610cb1612243565b610cb961231d565b565b5f5f5f5f5f60095f8781526020019081526020015f206040518060600160405290815f820154815260200160018201548152602001600282015f9054906101000a900460ff1615151515815250509050805f0151816020015182604001518360200151845f0151610d2c919061432c565b9450945094509450509193509193565b600d602052815f5260405f20602052805f5260405f205f91509150505481565b610d6461237f565b610d6c6123c9565b60018310158015610d7e575060108311155b610dbd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db490614204565b60405180910390fd5b5f82118015610dcd575060038211155b610e0c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e03906143a9565b60405180910390fd5b600b5f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16610e95576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e8c90614411565b60405180910390fd5b5f60095f8581526020019081526020015f209050806002015f9054906101000a900460ff16610ef9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef090614479565b60405180910390fd5b805f0154838260010154610f0d9190614497565b1115610f4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4590614514565b60405180910390fd5b60115f9054906101000a900460ff1615610fec5760105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16610feb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fe29061457c565b60405180910390fd5b5b5f600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205414806110815750621baf80600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205461107e9190614497565b42115b1561118d575f600190505b60108111611149575f600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055505f600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f208190555080806111419061459a565b91505061108c565b5042600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505b5f600c5f8681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f84826111ea919061424f565b90505f82036112f557600185600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205461124d9190614497565b111561128e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112859061462b565b60405180910390fd5b84600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8881526020019081526020015f205f8282546112e99190614497565b92505081905550611420565b600285600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205461134f9190614497565b1115611390576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161138790614693565b60405180910390fd5b84600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8881526020019081526020015f205f8282546113eb9190614497565b9250508190555061141f3330838773ffffffffffffffffffffffffffffffffffffffff16612418909392919063ffffffff16565b5b84836001015f8282546114339190614497565b9250508190555061145433878760405180602001604052805f81525061246d565b8373ffffffffffffffffffffffffffffffffffffffff16863373ffffffffffffffffffffffffffffffffffffffff167ff780016fefc156b52369a02f4e200b8ed44465d2a7728f2edeecc461f4cb7b4888856040516114b4929190613f40565b60405180910390a45050506114c7612503565b505050565b600181565b6114d9612243565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611547576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161153e906146fb565b60405180910390fd5b80600b5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f19c6e2fbd27c3204efb106f0081d2d7ffaf44da224ca04fbc0d8a262ba40f555826040516115e191906136a3565b60405180910390a25050565b6060815183511461163957815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401611630929190613f40565b60405180910390fd5b5f835167ffffffffffffffff8111156116555761165461382d565b5b6040519080825280602002602001820160405280156116835781602001602082028036833780820191505090505b5090505f5f90505b84518110156116ec576116c26116aa828761250d90919063ffffffff16565b6116bd838761252090919063ffffffff16565b610843565b8282815181106116d5576116d4614719565b5b60200260200101818152505080600101905061168b565b508091505092915050565b6116ff612243565b60018310158015611711575060108311155b611750576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161174790614204565b60405180910390fd5b8181600a5f8681526020019081526020015f209182611770929190614901565b50827fa21868eaf3c7f76e3920b694616a9b525dabdac615d6e3da5f3890aac442e05d83836040516117a39291906149fa565b60405180910390a2505050565b5f600560149054906101000a900460ff16905090565b600b602052805f5260405f205f915054906101000a900460ff1681565b6117eb612243565b6117f45f612533565b565b6009602052805f5260405f205f91509050805f015490806001015490806002015f9054906101000a900460ff16905083565b600f602052805f5260405f205f915090505481565b621baf8081565b5f5f600d5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f2054600e5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f2054915091509250929050565b6118f3612243565b6118fb6125f6565b565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61192d612243565b6119378282612659565b8173ffffffffffffffffffffffffffffffffffffffff167f8039bd6e4e7dba001c8840eb2e118d9d131246faa7d0d04335f7305127ec0b108260405161197d9190614a2b565b60405180910390a25050565b600880546119969061418a565b80601f01602080910402602001604051908101604052809291908181526020018280546119c29061418a565b8015611a0d5780601f106119e457610100808354040283529160200191611a0d565b820191905f5260205f20905b8154815290600101906020018083116119f057829003601f168201915b505050505081565b6010602052805f5260405f205f915054906101000a900460ff1681565b611a3a612243565b60018310158015611a4c575060108311155b611a8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8290614204565b60405180910390fd5b600b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611b14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0b90614411565b60405180910390fd5b80600c5f8581526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508173ffffffffffffffffffffffffffffffffffffffff16837ff98118827cdfda06446e0c5403630b61b01fb9047274a63a3b85ca96e04310f083604051611bac91906135f0565b60405180910390a3505050565b611bcb611bc46120bb565b83836127f4565b5050565b611bd7612243565b60018310158015611be9575060108311155b611c28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1f90614204565b60405180910390fd5b60095f8481526020019081526020015f2060010154821015611c7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c7690614a8e565b60405180910390fd5b8160095f8581526020019081526020015f205f01819055508060095f8581526020019081526020015f206002015f6101000a81548160ff021916908315150217905550827fc9528bf8de6505a75ee00ef8da15bb01df55030a984f2f66cd2f8d9ea7c625d38383604051611cf4929190614aac565b60405180910390a2505050565b611d09612243565b8060105f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d82604051611da391906136a3565b60405180910390a25050565b611db7612243565b8060115f6101000a81548160ff02191690831515021790555050565b600e602052815f5260405f20602052805f5260405f205f91509150505481565b601081565b600281565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b611e93612243565b60018210158015611ea5575060108211155b611ee4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611edb90614204565b60405180910390fd5b5f8111611f26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1d90614b1d565b60405180910390fd5b8060095f8481526020019081526020015f205f015f828254611f489190614497565b92505081905550817fef18524e45a9c3793f74939b40ae82cfa0160b2993a65ceee104545152736f8782604051611f7f91906135f0565b60405180910390a25050565b611f9c611f966120bb565b866120c2565b611fa985858585856129cd565b5050505050565b611fb8612243565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612028575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161201f9190613f67565b60405180910390fd5b61203181612533565b50565b600381565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806120ab57506120aa82612ad4565b5b9050919050565b5f612710905090565b5f33905090565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415801561210557506121038183611dfd565b155b156121495781816040517fe237d922000000000000000000000000000000000000000000000000000000008152600401612140929190614b3b565b60405180910390fd5b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036121bd575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016121b49190613f67565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361222d575f6040517f01a835140000000000000000000000000000000000000000000000000000000081526004016122249190613f67565b60405180910390fd5b61223c85858585856001612bb5565b5050505050565b61224b6120bb565b73ffffffffffffffffffffffffffffffffffffffff166122696118fd565b73ffffffffffffffffffffffffffffffffffffffff16146122c85761228c6120bb565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016122bf9190613f67565b60405180910390fd5b565b6122d78383836001612c5f565b61231857826040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161230f9190613f67565b60405180910390fd5b505050565b612325612cc1565b5f600560146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6123686120bb565b6040516123759190613f67565b60405180910390a1565b6123876117b0565b156123c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123be90614bac565b60405180910390fd5b565b60026006540361240e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161240590614c14565b60405180910390fd5b6002600681905550565b612426848484846001612d0a565b61246757836040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161245e9190613f67565b60405180910390fd5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036124dd575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016124d49190613f67565b60405180910390fd5b5f5f6124e98585612d7b565b915091506124fb5f878484875f612bb5565b505050505050565b6001600681905550565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6125fe61237f565b6001600560146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586126426120bb565b60405161264f9190613f67565b60405180910390a1565b5f6126626120b2565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156126c75781816040517f6f483d090000000000000000000000000000000000000000000000000000000081526004016126be929190614c62565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612737575f6040517fb6d9900a00000000000000000000000000000000000000000000000000000000815260040161272e9190613f67565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff1681525060035f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612864575f6040517f3e31884e00000000000000000000000000000000000000000000000000000000815260040161285b9190613f67565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036128d4575f6040517fced3e1000000000000000000000000000000000000000000000000000000000081526004016128cb9190613f67565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516129c091906136a3565b60405180910390a3505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612a3d575f6040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401612a349190613f67565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612aad575f6040517f01a83514000000000000000000000000000000000000000000000000000000008152600401612aa49190613f67565b60405180910390fd5b5f5f612ab98585612d7b565b91509150612acb87878484875f612bb5565b50505050505050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612b9e57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612bae5750612bad82612dab565b5b9050919050565b612bc186868686612e14565b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612c57575f612bfd6120bb565b90508115612c1857612c138188888888886131a7565b612c55565b5f612c2c5f8761252090919063ffffffff16565b90505f612c425f8761252090919063ffffffff16565b9050612c52838a8a85858a613356565b50505b505b505050505050565b5f5f63a9059cbb60e01b9050604051815f525f1960601c86166004528460245260205f60445f5f8b5af1925060015f51148316612cb3578383151615612ca7573d5f823e3d81fd5b5f873b113d1516831692505b806040525050949350505050565b612cc96117b0565b612d08576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cff90614cd3565b60405180910390fd5b565b5f5f6323b872dd60e01b9050604051815f525f1960601c87166004525f1960601c86166024528460445260205f60645f5f8c5af1925060015f51148316612d68578383151615612d5c573d5f823e3d81fd5b5f883b113d1516831692505b806040525f606052505095945050505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b8051825114612e5e57815181516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401612e55929190613f40565b60405180910390fd5b5f612e676120bb565b90505f5f90505b8351811015613066575f612e8b828661252090919063ffffffff16565b90505f612ea1838661252090919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614612fc4575f5f5f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015612f7057888183856040517f03dee4c5000000000000000000000000000000000000000000000000000000008152600401612f679493929190614cf1565b60405180910390fd5b8181035f5f8581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161461305957805f5f8481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546130519190614497565b925050819055505b5050806001019050612e6e565b506001835103613121575f6130845f8561252090919063ffffffff16565b90505f61309a5f8561252090919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051613112929190613f40565b60405180910390a450506131a0565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051613197929190614d34565b60405180910390a45b5050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b111561334e578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401613207959493929190614dbb565b6020604051808303815f875af192505050801561324257506040513d601f19601f8201168201806040525081019061323f9190614e35565b60015b6132c3573d805f8114613270576040519150601f19603f3d011682016040523d82523d5f602084013e613275565b606091505b505f8151036132bb57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016132b29190613f67565b60405180910390fd5b805160208201fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461334c57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016133439190613f67565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b11156134fd578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b81526004016133b6959493929190614e60565b6020604051808303815f875af19250505080156133f157506040513d601f19601f820116820180604052508101906133ee9190614e35565b60015b613472573d805f811461341f576040519150601f19603f3d011682016040523d82523d5f602084013e613424565b606091505b505f81510361346a57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016134619190613f67565b60405180910390fd5b805160208201fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146134fb57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016134f29190613f67565b60405180910390fd5b505b505050505050565b5f604051905090565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61353f82613516565b9050919050565b61354f81613535565b8114613559575f5ffd5b50565b5f8135905061356a81613546565b92915050565b5f819050919050565b61358281613570565b811461358c575f5ffd5b50565b5f8135905061359d81613579565b92915050565b5f5f604083850312156135b9576135b861350e565b5b5f6135c68582860161355c565b92505060206135d78582860161358f565b9150509250929050565b6135ea81613570565b82525050565b5f6020820190506136035f8301846135e1565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61363d81613609565b8114613647575f5ffd5b50565b5f8135905061365881613634565b92915050565b5f602082840312156136735761367261350e565b5b5f6136808482850161364a565b91505092915050565b5f8115159050919050565b61369d81613689565b82525050565b5f6020820190506136b65f830184613694565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6136fe826136bc565b61370881856136c6565b93506137188185602086016136d6565b613721816136e4565b840191505092915050565b5f6020820190508181035f83015261374481846136f4565b905092915050565b5f602082840312156137615761376061350e565b5b5f61376e8482850161358f565b91505092915050565b5f5f6040838503121561378d5761378c61350e565b5b5f61379a8582860161358f565b92505060206137ab8582860161355c565b9150509250929050565b5f5f604083850312156137cb576137ca61350e565b5b5f6137d88582860161358f565b92505060206137e98582860161358f565b9150509250929050565b6137fc81613535565b82525050565b5f6040820190506138155f8301856137f3565b61382260208301846135e1565b9392505050565b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613863826136e4565b810181811067ffffffffffffffff821117156138825761388161382d565b5b80604052505050565b5f613894613505565b90506138a0828261385a565b919050565b5f67ffffffffffffffff8211156138bf576138be61382d565b5b602082029050602081019050919050565b5f5ffd5b5f6138e66138e1846138a5565b61388b565b90508083825260208201905060208402830185811115613909576139086138d0565b5b835b81811015613932578061391e888261358f565b84526020840193505060208101905061390b565b5050509392505050565b5f82601f8301126139505761394f613829565b5b81356139608482602086016138d4565b91505092915050565b5f5ffd5b5f67ffffffffffffffff8211156139875761398661382d565b5b613990826136e4565b9050602081019050919050565b828183375f83830152505050565b5f6139bd6139b88461396d565b61388b565b9050828152602081018484840111156139d9576139d8613969565b5b6139e484828561399d565b509392505050565b5f82601f830112613a00576139ff613829565b5b8135613a108482602086016139ab565b91505092915050565b5f5f5f5f5f60a08688031215613a3257613a3161350e565b5b5f613a3f8882890161355c565b9550506020613a508882890161355c565b945050604086013567ffffffffffffffff811115613a7157613a70613512565b5b613a7d8882890161393c565b935050606086013567ffffffffffffffff811115613a9e57613a9d613512565b5b613aaa8882890161393c565b925050608086013567ffffffffffffffff811115613acb57613aca613512565b5b613ad7888289016139ec565b9150509295509295909350565b5f5f60408385031215613afa57613af961350e565b5b5f613b078582860161355c565b9250506020613b188582860161355c565b9150509250929050565b5f608082019050613b355f8301876135e1565b613b4260208301866135e1565b613b4f6040830185613694565b613b5c60608301846135e1565b95945050505050565b5f5f5f60608486031215613b7c57613b7b61350e565b5b5f613b898682870161358f565b9350506020613b9a8682870161358f565b9250506040613bab8682870161355c565b9150509250925092565b613bbe81613689565b8114613bc8575f5ffd5b50565b5f81359050613bd981613bb5565b92915050565b5f5f60408385031215613bf557613bf461350e565b5b5f613c028582860161355c565b9250506020613c1385828601613bcb565b9150509250929050565b5f67ffffffffffffffff821115613c3757613c3661382d565b5b602082029050602081019050919050565b5f613c5a613c5584613c1d565b61388b565b90508083825260208201905060208402830185811115613c7d57613c7c6138d0565b5b835b81811015613ca65780613c92888261355c565b845260208401935050602081019050613c7f565b5050509392505050565b5f82601f830112613cc457613cc3613829565b5b8135613cd4848260208601613c48565b91505092915050565b5f5f60408385031215613cf357613cf261350e565b5b5f83013567ffffffffffffffff811115613d1057613d0f613512565b5b613d1c85828601613cb0565b925050602083013567ffffffffffffffff811115613d3d57613d3c613512565b5b613d498582860161393c565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613d8581613570565b82525050565b5f613d968383613d7c565b60208301905092915050565b5f602082019050919050565b5f613db882613d53565b613dc28185613d5d565b9350613dcd83613d6d565b805f5b83811015613dfd578151613de48882613d8b565b9750613def83613da2565b925050600181019050613dd0565b5085935050505092915050565b5f6020820190508181035f830152613e228184613dae565b905092915050565b5f5ffd5b5f5f83601f840112613e4357613e42613829565b5b8235905067ffffffffffffffff811115613e6057613e5f613e2a565b5b602083019150836001820283011115613e7c57613e7b6138d0565b5b9250929050565b5f5f5f60408486031215613e9a57613e9961350e565b5b5f613ea78682870161358f565b935050602084013567ffffffffffffffff811115613ec857613ec7613512565b5b613ed486828701613e2e565b92509250509250925092565b5f60208284031215613ef557613ef461350e565b5b5f613f028482850161355c565b91505092915050565b5f606082019050613f1e5f8301866135e1565b613f2b60208301856135e1565b613f386040830184613694565b949350505050565b5f604082019050613f535f8301856135e1565b613f6060208301846135e1565b9392505050565b5f602082019050613f7a5f8301846137f3565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b613fa081613f80565b8114613faa575f5ffd5b50565b5f81359050613fbb81613f97565b92915050565b5f5f60408385031215613fd757613fd661350e565b5b5f613fe48582860161355c565b9250506020613ff585828601613fad565b9150509250929050565b5f5f5f606084860312156140165761401561350e565b5b5f6140238682870161358f565b93505060206140348682870161355c565b92505060406140458682870161358f565b9150509250925092565b5f5f5f606084860312156140665761406561350e565b5b5f6140738682870161358f565b93505060206140848682870161358f565b925050604061409586828701613bcb565b9150509250925092565b5f602082840312156140b4576140b361350e565b5b5f6140c184828501613bcb565b91505092915050565b5f5f5f5f5f60a086880312156140e3576140e261350e565b5b5f6140f08882890161355c565b95505060206141018882890161355c565b94505060406141128882890161358f565b93505060606141238882890161358f565b925050608086013567ffffffffffffffff81111561414457614143613512565b5b614150888289016139ec565b9150509295509295909350565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806141a157607f821691505b6020821081036141b4576141b361415d565b5b50919050565b7f496e76616c6964207479706500000000000000000000000000000000000000005f82015250565b5f6141ee600c836136c6565b91506141f9826141ba565b602082019050919050565b5f6020820190508181035f83015261421b816141e2565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61425982613570565b915061426483613570565b925082820261427281613570565b9150828204841483151761428957614288614222565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6142c782613570565b91506142d283613570565b9250826142e2576142e1614290565b5b828204905092915050565b5f815190506142fb81613579565b92915050565b5f602082840312156143165761431561350e565b5b5f614323848285016142ed565b91505092915050565b5f61433682613570565b915061434183613570565b925082820390508181111561435957614358614222565b5b92915050565b7f496e76616c696420616d6f756e740000000000000000000000000000000000005f82015250565b5f614393600e836136c6565b915061439e8261435f565b602082019050919050565b5f6020820190508181035f8301526143c081614387565b9050919050565b7f546f6b656e206e6f7420616c6c6f7765640000000000000000000000000000005f82015250565b5f6143fb6011836136c6565b9150614406826143c7565b602082019050919050565b5f6020820190508181035f830152614428816143ef565b9050919050565b7f5479706520696e616374697665000000000000000000000000000000000000005f82015250565b5f614463600d836136c6565b915061446e8261442f565b602082019050919050565b5f6020820190508181035f83015261449081614457565b9050919050565b5f6144a182613570565b91506144ac83613570565b92508282019050808211156144c4576144c3614222565b5b92915050565b7f536f6c64206f75740000000000000000000000000000000000000000000000005f82015250565b5f6144fe6008836136c6565b9150614509826144ca565b602082019050919050565b5f6020820190508181035f83015261452b816144f2565b9050919050565b7f4e6f742077686974656c697374656400000000000000000000000000000000005f82015250565b5f614566600f836136c6565b915061457182614532565b602082019050919050565b5f6020820190508181035f8301526145938161455a565b9050919050565b5f6145a482613570565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036145d6576145d5614222565b5b600182019050919050565b7f46726565206d696e74206c696d697400000000000000000000000000000000005f82015250565b5f614615600f836136c6565b9150614620826145e1565b602082019050919050565b5f6020820190508181035f83015261464281614609565b9050919050565b7f50616964206d696e74206c696d697400000000000000000000000000000000005f82015250565b5f61467d600f836136c6565b915061468882614649565b602082019050919050565b5f6020820190508181035f8301526146aa81614671565b9050919050565b7f5a65726f206164647265737300000000000000000000000000000000000000005f82015250565b5f6146e5600c836136c6565b91506146f0826146b1565b602082019050919050565b5f6020820190508181035f830152614712816146d9565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026147ac7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614771565b6147b68683614771565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6147f16147ec6147e784613570565b6147ce565b613570565b9050919050565b5f819050919050565b61480a836147d7565b61481e614816826147f8565b84845461477d565b825550505050565b5f5f905090565b614835614826565b614840818484614801565b505050565b5f5b828110156148665761485b5f82840161482d565b600181019050614847565b505050565b601f8211156148b957828211156148b85761488581614750565b61488e83614762565b61489785614762565b60208610156148a4575f90505b8083016148b382840382614845565b505050505b5b505050565b5f82821c905092915050565b5f6148d95f19846008026148be565b1980831691505092915050565b5f6148f183836148ca565b9150826002028217905092915050565b61490b8383614746565b67ffffffffffffffff8111156149245761492361382d565b5b61492e825461418a565b61493982828561486b565b5f601f831160018114614966575f8415614954578287013590505b61495e85826148e6565b8655506149c5565b601f19841661497486614750565b5f5b8281101561499b57848901358255600182019150602085019450602081019050614976565b868310156149b857848901356149b4601f8916826148ca565b8355505b6001600288020188555050505b50505050505050565b5f6149d983856136c6565b93506149e683858461399d565b6149ef836136e4565b840190509392505050565b5f6020820190508181035f830152614a138184866149ce565b90509392505050565b614a2581613f80565b82525050565b5f602082019050614a3e5f830184614a1c565b92915050565b7f42656c6f77206d696e74656400000000000000000000000000000000000000005f82015250565b5f614a78600c836136c6565b9150614a8382614a44565b602082019050919050565b5f6020820190508181035f830152614aa581614a6c565b9050919050565b5f604082019050614abf5f8301856135e1565b614acc6020830184613694565b9392505050565b7f496e76616c696420737570706c790000000000000000000000000000000000005f82015250565b5f614b07600e836136c6565b9150614b1282614ad3565b602082019050919050565b5f6020820190508181035f830152614b3481614afb565b9050919050565b5f604082019050614b4e5f8301856137f3565b614b5b60208301846137f3565b9392505050565b7f5061757361626c653a20706175736564000000000000000000000000000000005f82015250565b5f614b966010836136c6565b9150614ba182614b62565b602082019050919050565b5f6020820190508181035f830152614bc381614b8a565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c005f82015250565b5f614bfe601f836136c6565b9150614c0982614bca565b602082019050919050565b5f6020820190508181035f830152614c2b81614bf2565b9050919050565b5f614c4c614c47614c4284613f80565b6147ce565b613570565b9050919050565b614c5c81614c32565b82525050565b5f604082019050614c755f830185614c53565b614c8260208301846135e1565b9392505050565b7f5061757361626c653a206e6f74207061757365640000000000000000000000005f82015250565b5f614cbd6014836136c6565b9150614cc882614c89565b602082019050919050565b5f6020820190508181035f830152614cea81614cb1565b9050919050565b5f608082019050614d045f8301876137f3565b614d1160208301866135e1565b614d1e60408301856135e1565b614d2b60608301846135e1565b95945050505050565b5f6040820190508181035f830152614d4c8185613dae565b90508181036020830152614d608184613dae565b90509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f614d8d82614d69565b614d978185614d73565b9350614da78185602086016136d6565b614db0816136e4565b840191505092915050565b5f60a082019050614dce5f8301886137f3565b614ddb60208301876137f3565b8181036040830152614ded8186613dae565b90508181036060830152614e018185613dae565b90508181036080830152614e158184614d83565b90509695505050505050565b5f81519050614e2f81613634565b92915050565b5f60208284031215614e4a57614e4961350e565b5b5f614e5784828501614e21565b91505092915050565b5f60a082019050614e735f8301886137f3565b614e8060208301876137f3565b614e8d60408301866135e1565b614e9a60608301856135e1565b8181036080830152614eac8184614d83565b9050969550505050505056fea26469706673582212206bd34faf8a267156e48376a0357dc4c8061bdf2760bf0eaa62c05247701ddd2d64736f6c63430008200033
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610266575f3560e01c806379b2ab231161014f578063a9cdb8e1116100c1578063d9b39a1111610085578063d9b39a1114610783578063e985e9c5146107a1578063e9e7e599146107d1578063f242432a146107ed578063f2fde38b14610809578063f3b2db3f1461082557610266565b8063a9cdb8e1146106e1578063bc93233f146106fd578063c3b754dc14610719578063c9846d7014610735578063d9197c321461076557610266565b80638da5cb5b116101135780638da5cb5b146106215780638f2fc60b1461063f57806395d89b411461065b5780639b19251a14610679578063a200635b146106a9578063a22cb465146106c557610266565b806379b2ab23146105665780637af44c7f146105985780637dd0fd19146105c85780637de9376b146105e65780638456cb591461061757610266565b80633f4ba83a116101e8578063430884cf116101ac578063430884cf146104a65780634e1273f4146104c257806357f7789e146104f25780635c975abb1461050e578063697d312a1461052c578063715018a61461055c57610266565b80633f4ba83a146103ff5780634036ab781461040957806340e43ec61461043c57806341c6dead1461046c57806341cda2031461048857610266565b80631881d72c1161022f5780631881d72c146103365780632a55205a146103665780632b57cfbb146103975780632eb2c2d6146103c75780633aeac4e1146103e357610266565b8062fdd58e1461026a57806301ffc9a71461029a57806302ce5813146102ca57806306fdde03146102e85780630e89341c14610306575b5f5ffd5b610284600480360381019061027f91906135a3565b610843565b60405161029191906135f0565b60405180910390f35b6102b460048036038101906102af919061365e565b610898565b6040516102c191906136a3565b60405180910390f35b6102d26108a9565b6040516102df91906136a3565b60405180910390f35b6102f06108bb565b6040516102fd919061372c565b60405180910390f35b610320600480360381019061031b919061374c565b610947565b60405161032d919061372c565b60405180910390f35b610350600480360381019061034b9190613777565b610a39565b60405161035d91906135f0565b60405180910390f35b610380600480360381019061037b91906137b5565b610a59565b60405161038e929190613802565b60405180910390f35b6103b160048036038101906103ac9190613777565b610b7b565b6040516103be91906135f0565b60405180910390f35b6103e160048036038101906103dc9190613a19565b610bd1565b005b6103fd60048036038101906103f89190613ae4565b610bf6565b005b610407610ca9565b005b610423600480360381019061041e919061374c565b610cbb565b6040516104339493929190613b22565b60405180910390f35b610456600480360381019061045191906135a3565b610d3c565b60405161046391906135f0565b60405180910390f35b61048660048036038101906104819190613b65565b610d5c565b005b6104906114cc565b60405161049d91906135f0565b60405180910390f35b6104c060048036038101906104bb9190613bdf565b6114d1565b005b6104dc60048036038101906104d79190613cdd565b6115ed565b6040516104e99190613e0a565b60405180910390f35b61050c60048036038101906105079190613e83565b6116f7565b005b6105166117b0565b60405161052391906136a3565b60405180910390f35b61054660048036038101906105419190613ee0565b6117c6565b60405161055391906136a3565b60405180910390f35b6105646117e3565b005b610580600480360381019061057b919061374c565b6117f6565b60405161058f93929190613f0b565b60405180910390f35b6105b260048036038101906105ad9190613ee0565b611828565b6040516105bf91906135f0565b60405180910390f35b6105d061183d565b6040516105dd91906135f0565b60405180910390f35b61060060048036038101906105fb91906135a3565b611844565b60405161060e929190613f40565b60405180910390f35b61061f6118eb565b005b6106296118fd565b6040516106369190613f67565b60405180910390f35b61065960048036038101906106549190613fc1565b611925565b005b610663611989565b604051610670919061372c565b60405180910390f35b610693600480360381019061068e9190613ee0565b611a15565b6040516106a091906136a3565b60405180910390f35b6106c360048036038101906106be9190613fff565b611a32565b005b6106df60048036038101906106da9190613bdf565b611bb9565b005b6106fb60048036038101906106f6919061404f565b611bcf565b005b61071760048036038101906107129190613bdf565b611d01565b005b610733600480360381019061072e919061409f565b611daf565b005b61074f600480360381019061074a91906135a3565b611dd3565b60405161075c91906135f0565b60405180910390f35b61076d611df3565b60405161077a91906135f0565b60405180910390f35b61078b611df8565b60405161079891906135f0565b60405180910390f35b6107bb60048036038101906107b69190613ae4565b611dfd565b6040516107c891906136a3565b60405180910390f35b6107eb60048036038101906107e691906137b5565b611e8b565b005b610807600480360381019061080291906140ca565b611f8b565b005b610823600480360381019061081e9190613ee0565b611fb0565b005b61082d612034565b60405161083a91906135f0565b60405180910390f35b5f5f5f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f6108a282612039565b9050919050565b60115f9054906101000a900460ff1681565b600780546108c89061418a565b80601f01602080910402602001604051908101604052809291908181526020018280546108f49061418a565b801561093f5780601f106109165761010080835404028352916020019161093f565b820191905f5260205f20905b81548152906001019060200180831161092257829003601f168201915b505050505081565b60606001821015801561095b575060108211155b61099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099190614204565b60405180910390fd5b600a5f8381526020019081526020015f2080546109b69061418a565b80601f01602080910402602001604051908101604052809291908181526020018280546109e29061418a565b8015610a2d5780601f10610a0457610100808354040283529160200191610a2d565b820191905f5260205f20905b815481529060010190602001808311610a1057829003601f168201915b50505050509050919050565b600c602052815f5260405f20602052805f5260405f205f91509150505481565b5f5f5f60045f8681526020019081526020015f2090505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f825f0160149054906101000a90046bffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610b2d5760035f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915060035f0160149054906101000a90046bffffffffffffffffffffffff1690505b5f610b366120b2565b6bffffffffffffffffffffffff16826bffffffffffffffffffffffff1688610b5e919061424f565b610b6891906142bd565b9050828195509550505050509250929050565b5f600c5f8481526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b610be2610bdc6120bb565b866120c2565b610bef858585858561214d565b5050505050565b610bfe612243565b5f8273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c389190613f67565b602060405180830381865afa158015610c53573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c779190614301565b9050610ca482828573ffffffffffffffffffffffffffffffffffffffff166122ca9092919063ffffffff16565b505050565b610cb1612243565b610cb961231d565b565b5f5f5f5f5f60095f8781526020019081526020015f206040518060600160405290815f820154815260200160018201548152602001600282015f9054906101000a900460ff1615151515815250509050805f0151816020015182604001518360200151845f0151610d2c919061432c565b9450945094509450509193509193565b600d602052815f5260405f20602052805f5260405f205f91509150505481565b610d6461237f565b610d6c6123c9565b60018310158015610d7e575060108311155b610dbd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db490614204565b60405180910390fd5b5f82118015610dcd575060038211155b610e0c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e03906143a9565b60405180910390fd5b600b5f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16610e95576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e8c90614411565b60405180910390fd5b5f60095f8581526020019081526020015f209050806002015f9054906101000a900460ff16610ef9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef090614479565b60405180910390fd5b805f0154838260010154610f0d9190614497565b1115610f4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4590614514565b60405180910390fd5b60115f9054906101000a900460ff1615610fec5760105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16610feb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fe29061457c565b60405180910390fd5b5b5f600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205414806110815750621baf80600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205461107e9190614497565b42115b1561118d575f600190505b60108111611149575f600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20819055505f600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f208190555080806111419061459a565b91505061108c565b5042600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505b5f600c5f8681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f84826111ea919061424f565b90505f82036112f557600185600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205461124d9190614497565b111561128e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112859061462b565b60405180910390fd5b84600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8881526020019081526020015f205f8282546112e99190614497565b92505081905550611420565b600285600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205461134f9190614497565b1115611390576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161138790614693565b60405180910390fd5b84600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8881526020019081526020015f205f8282546113eb9190614497565b9250508190555061141f3330838773ffffffffffffffffffffffffffffffffffffffff16612418909392919063ffffffff16565b5b84836001015f8282546114339190614497565b9250508190555061145433878760405180602001604052805f81525061246d565b8373ffffffffffffffffffffffffffffffffffffffff16863373ffffffffffffffffffffffffffffffffffffffff167ff780016fefc156b52369a02f4e200b8ed44465d2a7728f2edeecc461f4cb7b4888856040516114b4929190613f40565b60405180910390a45050506114c7612503565b505050565b600181565b6114d9612243565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611547576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161153e906146fb565b60405180910390fd5b80600b5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f19c6e2fbd27c3204efb106f0081d2d7ffaf44da224ca04fbc0d8a262ba40f555826040516115e191906136a3565b60405180910390a25050565b6060815183511461163957815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401611630929190613f40565b60405180910390fd5b5f835167ffffffffffffffff8111156116555761165461382d565b5b6040519080825280602002602001820160405280156116835781602001602082028036833780820191505090505b5090505f5f90505b84518110156116ec576116c26116aa828761250d90919063ffffffff16565b6116bd838761252090919063ffffffff16565b610843565b8282815181106116d5576116d4614719565b5b60200260200101818152505080600101905061168b565b508091505092915050565b6116ff612243565b60018310158015611711575060108311155b611750576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161174790614204565b60405180910390fd5b8181600a5f8681526020019081526020015f209182611770929190614901565b50827fa21868eaf3c7f76e3920b694616a9b525dabdac615d6e3da5f3890aac442e05d83836040516117a39291906149fa565b60405180910390a2505050565b5f600560149054906101000a900460ff16905090565b600b602052805f5260405f205f915054906101000a900460ff1681565b6117eb612243565b6117f45f612533565b565b6009602052805f5260405f205f91509050805f015490806001015490806002015f9054906101000a900460ff16905083565b600f602052805f5260405f205f915090505481565b621baf8081565b5f5f600d5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f2054600e5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f2054915091509250929050565b6118f3612243565b6118fb6125f6565b565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61192d612243565b6119378282612659565b8173ffffffffffffffffffffffffffffffffffffffff167f8039bd6e4e7dba001c8840eb2e118d9d131246faa7d0d04335f7305127ec0b108260405161197d9190614a2b565b60405180910390a25050565b600880546119969061418a565b80601f01602080910402602001604051908101604052809291908181526020018280546119c29061418a565b8015611a0d5780601f106119e457610100808354040283529160200191611a0d565b820191905f5260205f20905b8154815290600101906020018083116119f057829003601f168201915b505050505081565b6010602052805f5260405f205f915054906101000a900460ff1681565b611a3a612243565b60018310158015611a4c575060108311155b611a8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8290614204565b60405180910390fd5b600b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611b14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0b90614411565b60405180910390fd5b80600c5f8581526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508173ffffffffffffffffffffffffffffffffffffffff16837ff98118827cdfda06446e0c5403630b61b01fb9047274a63a3b85ca96e04310f083604051611bac91906135f0565b60405180910390a3505050565b611bcb611bc46120bb565b83836127f4565b5050565b611bd7612243565b60018310158015611be9575060108311155b611c28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1f90614204565b60405180910390fd5b60095f8481526020019081526020015f2060010154821015611c7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c7690614a8e565b60405180910390fd5b8160095f8581526020019081526020015f205f01819055508060095f8581526020019081526020015f206002015f6101000a81548160ff021916908315150217905550827fc9528bf8de6505a75ee00ef8da15bb01df55030a984f2f66cd2f8d9ea7c625d38383604051611cf4929190614aac565b60405180910390a2505050565b611d09612243565b8060105f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d82604051611da391906136a3565b60405180910390a25050565b611db7612243565b8060115f6101000a81548160ff02191690831515021790555050565b600e602052815f5260405f20602052805f5260405f205f91509150505481565b601081565b600281565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b611e93612243565b60018210158015611ea5575060108211155b611ee4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611edb90614204565b60405180910390fd5b5f8111611f26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1d90614b1d565b60405180910390fd5b8060095f8481526020019081526020015f205f015f828254611f489190614497565b92505081905550817fef18524e45a9c3793f74939b40ae82cfa0160b2993a65ceee104545152736f8782604051611f7f91906135f0565b60405180910390a25050565b611f9c611f966120bb565b866120c2565b611fa985858585856129cd565b5050505050565b611fb8612243565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612028575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161201f9190613f67565b60405180910390fd5b61203181612533565b50565b600381565b5f7f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806120ab57506120aa82612ad4565b5b9050919050565b5f612710905090565b5f33905090565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415801561210557506121038183611dfd565b155b156121495781816040517fe237d922000000000000000000000000000000000000000000000000000000008152600401612140929190614b3b565b60405180910390fd5b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036121bd575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016121b49190613f67565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361222d575f6040517f01a835140000000000000000000000000000000000000000000000000000000081526004016122249190613f67565b60405180910390fd5b61223c85858585856001612bb5565b5050505050565b61224b6120bb565b73ffffffffffffffffffffffffffffffffffffffff166122696118fd565b73ffffffffffffffffffffffffffffffffffffffff16146122c85761228c6120bb565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016122bf9190613f67565b60405180910390fd5b565b6122d78383836001612c5f565b61231857826040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161230f9190613f67565b60405180910390fd5b505050565b612325612cc1565b5f600560146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6123686120bb565b6040516123759190613f67565b60405180910390a1565b6123876117b0565b156123c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123be90614bac565b60405180910390fd5b565b60026006540361240e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161240590614c14565b60405180910390fd5b6002600681905550565b612426848484846001612d0a565b61246757836040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161245e9190613f67565b60405180910390fd5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036124dd575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016124d49190613f67565b60405180910390fd5b5f5f6124e98585612d7b565b915091506124fb5f878484875f612bb5565b505050505050565b6001600681905550565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6125fe61237f565b6001600560146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586126426120bb565b60405161264f9190613f67565b60405180910390a1565b5f6126626120b2565b6bffffffffffffffffffffffff16905080826bffffffffffffffffffffffff1611156126c75781816040517f6f483d090000000000000000000000000000000000000000000000000000000081526004016126be929190614c62565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612737575f6040517fb6d9900a00000000000000000000000000000000000000000000000000000000815260040161272e9190613f67565b60405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff168152602001836bffffffffffffffffffffffff1681525060035f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151815f0160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612864575f6040517f3e31884e00000000000000000000000000000000000000000000000000000000815260040161285b9190613f67565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036128d4575f6040517fced3e1000000000000000000000000000000000000000000000000000000000081526004016128cb9190613f67565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516129c091906136a3565b60405180910390a3505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612a3d575f6040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401612a349190613f67565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612aad575f6040517f01a83514000000000000000000000000000000000000000000000000000000008152600401612aa49190613f67565b60405180910390fd5b5f5f612ab98585612d7b565b91509150612acb87878484875f612bb5565b50505050505050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612b9e57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612bae5750612bad82612dab565b5b9050919050565b612bc186868686612e14565b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612c57575f612bfd6120bb565b90508115612c1857612c138188888888886131a7565b612c55565b5f612c2c5f8761252090919063ffffffff16565b90505f612c425f8761252090919063ffffffff16565b9050612c52838a8a85858a613356565b50505b505b505050505050565b5f5f63a9059cbb60e01b9050604051815f525f1960601c86166004528460245260205f60445f5f8b5af1925060015f51148316612cb3578383151615612ca7573d5f823e3d81fd5b5f873b113d1516831692505b806040525050949350505050565b612cc96117b0565b612d08576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cff90614cd3565b60405180910390fd5b565b5f5f6323b872dd60e01b9050604051815f525f1960601c87166004525f1960601c86166024528460445260205f60645f5f8c5af1925060015f51148316612d68578383151615612d5c573d5f823e3d81fd5b5f883b113d1516831692505b806040525f606052505095945050505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b8051825114612e5e57815181516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401612e55929190613f40565b60405180910390fd5b5f612e676120bb565b90505f5f90505b8351811015613066575f612e8b828661252090919063ffffffff16565b90505f612ea1838661252090919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614612fc4575f5f5f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015612f7057888183856040517f03dee4c5000000000000000000000000000000000000000000000000000000008152600401612f679493929190614cf1565b60405180910390fd5b8181035f5f8581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161461305957805f5f8481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546130519190614497565b925050819055505b5050806001019050612e6e565b506001835103613121575f6130845f8561252090919063ffffffff16565b90505f61309a5f8561252090919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051613112929190613f40565b60405180910390a450506131a0565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051613197929190614d34565b60405180910390a45b5050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b111561334e578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401613207959493929190614dbb565b6020604051808303815f875af192505050801561324257506040513d601f19601f8201168201806040525081019061323f9190614e35565b60015b6132c3573d805f8114613270576040519150601f19603f3d011682016040523d82523d5f602084013e613275565b606091505b505f8151036132bb57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016132b29190613f67565b60405180910390fd5b805160208201fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461334c57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016133439190613f67565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b11156134fd578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b81526004016133b6959493929190614e60565b6020604051808303815f875af19250505080156133f157506040513d601f19601f820116820180604052508101906133ee9190614e35565b60015b613472573d805f811461341f576040519150601f19603f3d011682016040523d82523d5f602084013e613424565b606091505b505f81510361346a57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016134619190613f67565b60405180910390fd5b805160208201fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146134fb57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016134f29190613f67565b60405180910390fd5b505b505050505050565b5f604051905090565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61353f82613516565b9050919050565b61354f81613535565b8114613559575f5ffd5b50565b5f8135905061356a81613546565b92915050565b5f819050919050565b61358281613570565b811461358c575f5ffd5b50565b5f8135905061359d81613579565b92915050565b5f5f604083850312156135b9576135b861350e565b5b5f6135c68582860161355c565b92505060206135d78582860161358f565b9150509250929050565b6135ea81613570565b82525050565b5f6020820190506136035f8301846135e1565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61363d81613609565b8114613647575f5ffd5b50565b5f8135905061365881613634565b92915050565b5f602082840312156136735761367261350e565b5b5f6136808482850161364a565b91505092915050565b5f8115159050919050565b61369d81613689565b82525050565b5f6020820190506136b65f830184613694565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6136fe826136bc565b61370881856136c6565b93506137188185602086016136d6565b613721816136e4565b840191505092915050565b5f6020820190508181035f83015261374481846136f4565b905092915050565b5f602082840312156137615761376061350e565b5b5f61376e8482850161358f565b91505092915050565b5f5f6040838503121561378d5761378c61350e565b5b5f61379a8582860161358f565b92505060206137ab8582860161355c565b9150509250929050565b5f5f604083850312156137cb576137ca61350e565b5b5f6137d88582860161358f565b92505060206137e98582860161358f565b9150509250929050565b6137fc81613535565b82525050565b5f6040820190506138155f8301856137f3565b61382260208301846135e1565b9392505050565b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613863826136e4565b810181811067ffffffffffffffff821117156138825761388161382d565b5b80604052505050565b5f613894613505565b90506138a0828261385a565b919050565b5f67ffffffffffffffff8211156138bf576138be61382d565b5b602082029050602081019050919050565b5f5ffd5b5f6138e66138e1846138a5565b61388b565b90508083825260208201905060208402830185811115613909576139086138d0565b5b835b81811015613932578061391e888261358f565b84526020840193505060208101905061390b565b5050509392505050565b5f82601f8301126139505761394f613829565b5b81356139608482602086016138d4565b91505092915050565b5f5ffd5b5f67ffffffffffffffff8211156139875761398661382d565b5b613990826136e4565b9050602081019050919050565b828183375f83830152505050565b5f6139bd6139b88461396d565b61388b565b9050828152602081018484840111156139d9576139d8613969565b5b6139e484828561399d565b509392505050565b5f82601f830112613a00576139ff613829565b5b8135613a108482602086016139ab565b91505092915050565b5f5f5f5f5f60a08688031215613a3257613a3161350e565b5b5f613a3f8882890161355c565b9550506020613a508882890161355c565b945050604086013567ffffffffffffffff811115613a7157613a70613512565b5b613a7d8882890161393c565b935050606086013567ffffffffffffffff811115613a9e57613a9d613512565b5b613aaa8882890161393c565b925050608086013567ffffffffffffffff811115613acb57613aca613512565b5b613ad7888289016139ec565b9150509295509295909350565b5f5f60408385031215613afa57613af961350e565b5b5f613b078582860161355c565b9250506020613b188582860161355c565b9150509250929050565b5f608082019050613b355f8301876135e1565b613b4260208301866135e1565b613b4f6040830185613694565b613b5c60608301846135e1565b95945050505050565b5f5f5f60608486031215613b7c57613b7b61350e565b5b5f613b898682870161358f565b9350506020613b9a8682870161358f565b9250506040613bab8682870161355c565b9150509250925092565b613bbe81613689565b8114613bc8575f5ffd5b50565b5f81359050613bd981613bb5565b92915050565b5f5f60408385031215613bf557613bf461350e565b5b5f613c028582860161355c565b9250506020613c1385828601613bcb565b9150509250929050565b5f67ffffffffffffffff821115613c3757613c3661382d565b5b602082029050602081019050919050565b5f613c5a613c5584613c1d565b61388b565b90508083825260208201905060208402830185811115613c7d57613c7c6138d0565b5b835b81811015613ca65780613c92888261355c565b845260208401935050602081019050613c7f565b5050509392505050565b5f82601f830112613cc457613cc3613829565b5b8135613cd4848260208601613c48565b91505092915050565b5f5f60408385031215613cf357613cf261350e565b5b5f83013567ffffffffffffffff811115613d1057613d0f613512565b5b613d1c85828601613cb0565b925050602083013567ffffffffffffffff811115613d3d57613d3c613512565b5b613d498582860161393c565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613d8581613570565b82525050565b5f613d968383613d7c565b60208301905092915050565b5f602082019050919050565b5f613db882613d53565b613dc28185613d5d565b9350613dcd83613d6d565b805f5b83811015613dfd578151613de48882613d8b565b9750613def83613da2565b925050600181019050613dd0565b5085935050505092915050565b5f6020820190508181035f830152613e228184613dae565b905092915050565b5f5ffd5b5f5f83601f840112613e4357613e42613829565b5b8235905067ffffffffffffffff811115613e6057613e5f613e2a565b5b602083019150836001820283011115613e7c57613e7b6138d0565b5b9250929050565b5f5f5f60408486031215613e9a57613e9961350e565b5b5f613ea78682870161358f565b935050602084013567ffffffffffffffff811115613ec857613ec7613512565b5b613ed486828701613e2e565b92509250509250925092565b5f60208284031215613ef557613ef461350e565b5b5f613f028482850161355c565b91505092915050565b5f606082019050613f1e5f8301866135e1565b613f2b60208301856135e1565b613f386040830184613694565b949350505050565b5f604082019050613f535f8301856135e1565b613f6060208301846135e1565b9392505050565b5f602082019050613f7a5f8301846137f3565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b613fa081613f80565b8114613faa575f5ffd5b50565b5f81359050613fbb81613f97565b92915050565b5f5f60408385031215613fd757613fd661350e565b5b5f613fe48582860161355c565b9250506020613ff585828601613fad565b9150509250929050565b5f5f5f606084860312156140165761401561350e565b5b5f6140238682870161358f565b93505060206140348682870161355c565b92505060406140458682870161358f565b9150509250925092565b5f5f5f606084860312156140665761406561350e565b5b5f6140738682870161358f565b93505060206140848682870161358f565b925050604061409586828701613bcb565b9150509250925092565b5f602082840312156140b4576140b361350e565b5b5f6140c184828501613bcb565b91505092915050565b5f5f5f5f5f60a086880312156140e3576140e261350e565b5b5f6140f08882890161355c565b95505060206141018882890161355c565b94505060406141128882890161358f565b93505060606141238882890161358f565b925050608086013567ffffffffffffffff81111561414457614143613512565b5b614150888289016139ec565b9150509295509295909350565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806141a157607f821691505b6020821081036141b4576141b361415d565b5b50919050565b7f496e76616c6964207479706500000000000000000000000000000000000000005f82015250565b5f6141ee600c836136c6565b91506141f9826141ba565b602082019050919050565b5f6020820190508181035f83015261421b816141e2565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61425982613570565b915061426483613570565b925082820261427281613570565b9150828204841483151761428957614288614222565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6142c782613570565b91506142d283613570565b9250826142e2576142e1614290565b5b828204905092915050565b5f815190506142fb81613579565b92915050565b5f602082840312156143165761431561350e565b5b5f614323848285016142ed565b91505092915050565b5f61433682613570565b915061434183613570565b925082820390508181111561435957614358614222565b5b92915050565b7f496e76616c696420616d6f756e740000000000000000000000000000000000005f82015250565b5f614393600e836136c6565b915061439e8261435f565b602082019050919050565b5f6020820190508181035f8301526143c081614387565b9050919050565b7f546f6b656e206e6f7420616c6c6f7765640000000000000000000000000000005f82015250565b5f6143fb6011836136c6565b9150614406826143c7565b602082019050919050565b5f6020820190508181035f830152614428816143ef565b9050919050565b7f5479706520696e616374697665000000000000000000000000000000000000005f82015250565b5f614463600d836136c6565b915061446e8261442f565b602082019050919050565b5f6020820190508181035f83015261449081614457565b9050919050565b5f6144a182613570565b91506144ac83613570565b92508282019050808211156144c4576144c3614222565b5b92915050565b7f536f6c64206f75740000000000000000000000000000000000000000000000005f82015250565b5f6144fe6008836136c6565b9150614509826144ca565b602082019050919050565b5f6020820190508181035f83015261452b816144f2565b9050919050565b7f4e6f742077686974656c697374656400000000000000000000000000000000005f82015250565b5f614566600f836136c6565b915061457182614532565b602082019050919050565b5f6020820190508181035f8301526145938161455a565b9050919050565b5f6145a482613570565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036145d6576145d5614222565b5b600182019050919050565b7f46726565206d696e74206c696d697400000000000000000000000000000000005f82015250565b5f614615600f836136c6565b9150614620826145e1565b602082019050919050565b5f6020820190508181035f83015261464281614609565b9050919050565b7f50616964206d696e74206c696d697400000000000000000000000000000000005f82015250565b5f61467d600f836136c6565b915061468882614649565b602082019050919050565b5f6020820190508181035f8301526146aa81614671565b9050919050565b7f5a65726f206164647265737300000000000000000000000000000000000000005f82015250565b5f6146e5600c836136c6565b91506146f0826146b1565b602082019050919050565b5f6020820190508181035f830152614712816146d9565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026147ac7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614771565b6147b68683614771565b95508019841693508086168417925050509392505050565b5f819050919050565b5f6147f16147ec6147e784613570565b6147ce565b613570565b9050919050565b5f819050919050565b61480a836147d7565b61481e614816826147f8565b84845461477d565b825550505050565b5f5f905090565b614835614826565b614840818484614801565b505050565b5f5b828110156148665761485b5f82840161482d565b600181019050614847565b505050565b601f8211156148b957828211156148b85761488581614750565b61488e83614762565b61489785614762565b60208610156148a4575f90505b8083016148b382840382614845565b505050505b5b505050565b5f82821c905092915050565b5f6148d95f19846008026148be565b1980831691505092915050565b5f6148f183836148ca565b9150826002028217905092915050565b61490b8383614746565b67ffffffffffffffff8111156149245761492361382d565b5b61492e825461418a565b61493982828561486b565b5f601f831160018114614966575f8415614954578287013590505b61495e85826148e6565b8655506149c5565b601f19841661497486614750565b5f5b8281101561499b57848901358255600182019150602085019450602081019050614976565b868310156149b857848901356149b4601f8916826148ca565b8355505b6001600288020188555050505b50505050505050565b5f6149d983856136c6565b93506149e683858461399d565b6149ef836136e4565b840190509392505050565b5f6020820190508181035f830152614a138184866149ce565b90509392505050565b614a2581613f80565b82525050565b5f602082019050614a3e5f830184614a1c565b92915050565b7f42656c6f77206d696e74656400000000000000000000000000000000000000005f82015250565b5f614a78600c836136c6565b9150614a8382614a44565b602082019050919050565b5f6020820190508181035f830152614aa581614a6c565b9050919050565b5f604082019050614abf5f8301856135e1565b614acc6020830184613694565b9392505050565b7f496e76616c696420737570706c790000000000000000000000000000000000005f82015250565b5f614b07600e836136c6565b9150614b1282614ad3565b602082019050919050565b5f6020820190508181035f830152614b3481614afb565b9050919050565b5f604082019050614b4e5f8301856137f3565b614b5b60208301846137f3565b9392505050565b7f5061757361626c653a20706175736564000000000000000000000000000000005f82015250565b5f614b966010836136c6565b9150614ba182614b62565b602082019050919050565b5f6020820190508181035f830152614bc381614b8a565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c005f82015250565b5f614bfe601f836136c6565b9150614c0982614bca565b602082019050919050565b5f6020820190508181035f830152614c2b81614bf2565b9050919050565b5f614c4c614c47614c4284613f80565b6147ce565b613570565b9050919050565b614c5c81614c32565b82525050565b5f604082019050614c755f830185614c53565b614c8260208301846135e1565b9392505050565b7f5061757361626c653a206e6f74207061757365640000000000000000000000005f82015250565b5f614cbd6014836136c6565b9150614cc882614c89565b602082019050919050565b5f6020820190508181035f830152614cea81614cb1565b9050919050565b5f608082019050614d045f8301876137f3565b614d1160208301866135e1565b614d1e60408301856135e1565b614d2b60608301846135e1565b95945050505050565b5f6040820190508181035f830152614d4c8185613dae565b90508181036020830152614d608184613dae565b90509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f614d8d82614d69565b614d978185614d73565b9350614da78185602086016136d6565b614db0816136e4565b840191505092915050565b5f60a082019050614dce5f8301886137f3565b614ddb60208301876137f3565b8181036040830152614ded8186613dae565b90508181036060830152614e018185613dae565b90508181036080830152614e158184614d83565b90509695505050505050565b5f81519050614e2f81613634565b92915050565b5f60208284031215614e4a57614e4961350e565b5b5f614e5784828501614e21565b91505092915050565b5f60a082019050614e735f8301886137f3565b614e8060208301876137f3565b614e8d60408301866135e1565b614e9a60608301856135e1565b8181036080830152614eac8184614d83565b9050969550505050505056fea26469706673582212206bd34faf8a267156e48376a0357dc4c8061bdf2760bf0eaa62c05247701ddd2d64736f6c63430008200033
Deployed Bytecode Sourcemap
191802:7901:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;141028:134;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;199492:204;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;192855:35;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;191926:39;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;198549:170;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;192512:69;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;188642:673;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;199085:127;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;142575:307;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;196185:196;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;195949:53;;;:::i;:::-;;198727:350;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;192590:73;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;196689:1837;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;192105:41;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;195315:238;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;141328:567;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;195089:218;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;159765:86;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;192453:52;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;157256:103;;;:::i;:::-;;192350:43;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;192750:48;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;192054:44;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;199220:264;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;195892:49;;;:::i;:::-;;156581:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;196010:167;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;191972:29;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;192807:41;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;195561:323;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;141933:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;194429:350;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;196389:164;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;196561:105;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;192670:73;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;192010:37;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;192153:41;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;142117:159;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;194787:294;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;142314:223;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;157514:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;192201:34;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;141028:134;141105:7;141132:9;:13;141142:2;141132:13;;;;;;;;;;;:22;141146:7;141132:22;;;;;;;;;;;;;;;;141125:29;;141028:134;;;;:::o;199492:204::-;199621:4;199652:36;199676:11;199652:23;:36::i;:::-;199645:43;;199492:204;;;:::o;192855:35::-;;;;;;;;;;;;;:::o;191926:39::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;198549:170::-;198603:13;198643:1;198638:2;:6;;:24;;;;;192045:2;198648;:14;;198638:24;198630:48;;;;;;;;;;;;:::i;:::-;;;;;;;;;198698:9;:13;198708:2;198698:13;;;;;;;;;;;198691:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;198549:170;;;:::o;192512:69::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;188642:673::-;188753:16;188771:14;188798:32;188833:17;:26;188851:7;188833:26;;;;;;;;;;;188798:61;;188870:23;188896:12;:21;;;;;;;;;;;;188870:47;;188928:22;188953:12;:28;;;;;;;;;;;;188928:53;;189025:1;188998:29;;:15;:29;;;188994:176;;189062:19;:28;;;;;;;;;;;;189044:46;;189123:19;:35;;;;;;;;;;;;189105:53;;188994:176;189182:21;189238:17;:15;:17::i;:::-;189206:49;;189219:15;189207:27;;:9;:27;;;;:::i;:::-;189206:49;;;;:::i;:::-;189182:73;;189276:15;189293:13;189268:39;;;;;;;;188642:673;;;;;:::o;199085:127::-;199151:7;199179:14;:18;199194:2;199179:18;;;;;;;;;;;:25;199198:5;199179:25;;;;;;;;;;;;;;;;199172:32;;199085:127;;;;:::o;142575:307::-;142776:36;142793:12;:10;:12::i;:::-;142807:4;142776:16;:36::i;:::-;142823:51;142846:4;142852:2;142856:3;142861:6;142869:4;142823:22;:51::i;:::-;142575:307;;;;;:::o;196185:196::-;156467:13;:11;:13::i;:::-;196266:15:::1;196291:5;196284:23;;;196316:4;196284:38;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;196266:56;;196335:38;196362:2;196365:7;196342:5;196335:26;;;;:38;;;;;:::i;:::-;196253:128;196185:196:::0;;:::o;195949:53::-;156467:13;:11;:13::i;:::-;195989:10:::1;:8;:10::i;:::-;195949:53::o:0;198727:350::-;198805:17;198823:14;198838:11;198850:17;198887:18;198908:8;:12;198917:2;198908:12;;;;;;;;;;;198887:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;198954:3;:13;;;198982:3;:10;;;199007:3;:10;;;199048:3;:10;;;199032:3;:13;;;:26;;;;:::i;:::-;198933:136;;;;;;;;;198727:350;;;;;:::o;192590:73::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;196689:1837::-;159370:19;:17;:19::i;:::-;184347:21:::1;:19;:21::i;:::-;196854:1:::2;196849:2;:6;;:24;;;;;192045:2;196859;:14;;196849:24;196841:48;;;;;;;;;;;;:::i;:::-;;;;;;;;;196916:1;196908:6;:9;:29;;;;;192234:1;196921:6;:16;;196908:29;196900:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;196974:20;:34;196995:12;196974:34;;;;;;;;;;;;;;;;;;;;;;;;;196966:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;197042:19;197064:8;:12;197073:2;197064:12;;;;;;;;;;;197042:34;;197097:3;:10;;;;;;;;;;;;197089:35;;;;;;;;;;;;:::i;:::-;;;;;;;;;197166:3;:13;;;197156:6;197143:3;:10;;;:19;;;;:::i;:::-;:36;;197135:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;197207:15;;;;;;;;;;;197204:94;;;197246:9;:21;197256:10;197246:21;;;;;;;;;;;;;;;;;;;;;;;;;197238:48;;;;;;;;;;;;:::i;:::-;;;;;;;;;197204:94;197342:1;197313:13;:25;197327:10;197313:25;;;;;;;;;;;;;;;;:30;:90;;;;192091:7;197365:13;:25;197379:10;197365:25;;;;;;;;;;;;;;;;:38;;;;:::i;:::-;197347:15;:56;197313:90;197310:365;;;197424:9;197436:1;197424:13;;197420:172;192045:2;197439:1;:13;197420:172;;197516:1;197480:18;:30;197499:10;197480:30;;;;;;;;;;;;;;;:33;197511:1;197480:33;;;;;;;;;;;:37;;;;197572:1;197536:18;:30;197555:10;197536:30;;;;;;;;;;;;;;;:33;197567:1;197536:33;;;;;;;;;;;:37;;;;197454:3;;;;;:::i;:::-;;;;197420:172;;;;197640:15;197612:13;:25;197626:10;197612:25;;;;;;;;;;;;;;;:43;;;;197310:365;197687:17;197707:14;:18;197722:2;197707:18;;;;;;;;;;;:32;197726:12;197707:32;;;;;;;;;;;;;;;;197687:52;;197750:18;197783:6;197771:9;:18;;;;:::i;:::-;197750:39;;197818:1;197805:9;:14:::0;197802:571:::2;;192145:1;197900:6;197863:18;:30;197882:10;197863:30;;;;;;;;;;;;;;;:34;197894:2;197863:34;;;;;;;;;;;;:43;;;;:::i;:::-;:60;;197837:137;;;;;;;;;;;;:::i;:::-;;;;;;;;;198029:6;197991:18;:30;198010:10;197991:30;;;;;;;;;;;;;;;:34;198022:2;197991:34;;;;;;;;;;;;:44;;;;;;;:::i;:::-;;;;;;;;197802:571;;;192193:1;198135:6;198098:18;:30;198117:10;198098:30;;;;;;;;;;;;;;;:34;198129:2;198098:34;;;;;;;;;;;;:43;;;;:::i;:::-;:60;;198072:137;;;;;;;;;;;;:::i;:::-;;;;;;;;;198264:6;198226:18;:30;198245:10;198226:30;;;;;;;;;;;;;;;:34;198257:2;198226:34;;;;;;;;;;;;:44;;;;;;;:::i;:::-;;;;;;;;198287:74;198325:10;198344:4;198350:10;198294:12;198287:37;;;;:74;;;;;;:::i;:::-;197802:571;198399:6;198385:3;:10;;;:20;;;;;;;:::i;:::-;;;;;;;;198418:30;198424:10;198435:2;198438:6;198418:30;;;;;;;;;;;::::0;:5:::2;:30::i;:::-;198494:12;198466:52;;198484:2;198473:10;198466:52;;;198487:6;198507:10;198466:52;;;;;;;:::i;:::-;;;;;;;;196828:1698;;;184391:20:::1;:18;:20::i;:::-;196689:1837:::0;;;:::o;192105:41::-;192145:1;192105:41;:::o;195315:238::-;156467:13;:11;:13::i;:::-;195425:1:::1;195408:19;;:5;:19;;::::0;195400:43:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;195486:7;195456:20;:27;195477:5;195456:27;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;195531:5;195511:34;;;195537:7;195511:34;;;;;;:::i;:::-;;;;;;;;195315:238:::0;;:::o;141328:567::-;141455:16;141507:3;:10;141488:8;:15;:29;141484:123;;141567:3;:10;141579:8;:15;141541:54;;;;;;;;;;;;:::i;:::-;;;;;;;;141484:123;141619:30;141666:8;:15;141652:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;141619:63;;141700:9;141712:1;141700:13;;141695:160;141719:8;:15;141715:1;:19;141695:160;;;141775:68;141785:30;141813:1;141785:8;:27;;:30;;;;:::i;:::-;141817:25;141840:1;141817:3;:22;;:25;;;;:::i;:::-;141775:9;:68::i;:::-;141756:13;141770:1;141756:16;;;;;;;;:::i;:::-;;;;;;;:87;;;;;141736:3;;;;;141695:160;;;;141874:13;141867:20;;;141328:567;;;;:::o;195089:218::-;156467:13;:11;:13::i;:::-;195190:1:::1;195185:2;:6;;:24;;;;;192045:2;195195;:14;;195185:24;195177:48;;;;;;;;;;;;:::i;:::-;;;;;;;;;195254:6;;195238:9;:13;195248:2;195238:13;;;;;;;;;;;:22;;;;;;;:::i;:::-;;195289:2;195278:21;195292:6;;195278:21;;;;;;;:::i;:::-;;;;;;;;195089:218:::0;;;:::o;159765:86::-;159812:4;159836:7;;;;;;;;;;;159829:14;;159765:86;:::o;192453:52::-;;;;;;;;;;;;;;;;;;;;;;:::o;157256:103::-;156467:13;:11;:13::i;:::-;157321:30:::1;157348:1;157321:18;:30::i;:::-;157256:103::o:0;192350:43::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;192750:48::-;;;;;;;;;;;;;;;;;:::o;192054:44::-;192091:7;192054:44;:::o;199220:264::-;199316:18;199335;199394;:24;199413:4;199394:24;;;;;;;;;;;;;;;:28;199419:2;199394:28;;;;;;;;;;;;199437:18;:24;199456:4;199437:24;;;;;;;;;;;;;;;:28;199462:2;199437:28;;;;;;;;;;;;199373:103;;;;199220:264;;;;;:::o;195892:49::-;156467:13;:11;:13::i;:::-;195930:8:::1;:6;:8::i;:::-;195892:49::o:0;156581:87::-;156627:7;156654:6;;;;;;;;;;;156647:13;;156581:87;:::o;196010:167::-;156467:13;:11;:13::i;:::-;196091:32:::1;196110:8;196119:3;196091:18;:32::i;:::-;196156:8;196141:28;;;196165:3;196141:28;;;;;;:::i;:::-;;;;;;;;196010:167:::0;;:::o;191972:29::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;192807:41::-;;;;;;;;;;;;;;;;;;;;;;:::o;195561:323::-;156467:13;:11;:13::i;:::-;195673:1:::1;195668:2;:6;;:24;;;;;192045:2;195678;:14;;195668:24;195660:48;;;;;;;;;;;;:::i;:::-;;;;;;;;;195727:20;:27;195748:5;195727:27;;;;;;;;;;;;;;;;;;;;;;;;;195719:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;195816:5;195788:14;:18;195803:2;195788:18;;;;;;;;;;;:25;195807:5;195788:25;;;;;;;;;;;;;;;:33;;;;195864:5;195839:37;;195861:2;195839:37;195870:5;195839:37;;;;;;:::i;:::-;;;;;;;;195561:323:::0;;;:::o;141933:146::-;142019:52;142038:12;:10;:12::i;:::-;142052:8;142062;142019:18;:52::i;:::-;141933:146;;:::o;194429:350::-;156467:13;:11;:13::i;:::-;194533:1:::1;194528:2;:6;;:24;;;;;192045:2;194538;:14;;194528:24;194520:48;;;;;;;;;;;;:::i;:::-;;;;;;;;;194600:8;:12;194609:2;194600:12;;;;;;;;;;;:19;;;194587:9;:32;;194579:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;194673:9;194648:8;:12;194657:2;194648:12;;;;;;;;;;;:22;;:34;;;;194715:6;194693:8;:12;194702:2;194693:12;;;;;;;;;;;:19;;;:28;;;;;;;;;;;;;;;;;;194751:2;194739:32;194754:9;194764:6;194739:32;;;;;;;:::i;:::-;;;;;;;;194429:350:::0;;;:::o;196389:164::-;156467:13;:11;:13::i;:::-;196490:7:::1;196472:9;:15;196482:4;196472:15;;;;;;;;;;;;;;;;:25;;;;;;;;;;;;;;;;;;196532:4;196515:30;;;196537:7;196515:30;;;;;;:::i;:::-;;;;;;;;196389:164:::0;;:::o;196561:105::-;156467:13;:11;:13::i;:::-;196652:6:::1;196634:15;;:24;;;;;;;;;;;;;;;;;;196561:105:::0;:::o;192670:73::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;192010:37::-;192045:2;192010:37;:::o;192153:41::-;192193:1;192153:41;:::o;142117:159::-;142207:4;142231:18;:27;142250:7;142231:27;;;;;;;;;;;;;;;:37;142259:8;142231:37;;;;;;;;;;;;;;;;;;;;;;;;;142224:44;;142117:159;;;;:::o;194787:294::-;156467:13;:11;:13::i;:::-;194888:1:::1;194883:2;:6;;:24;;;;;192045:2;194893;:14;;194883:24;194875:48;;;;;;;;;;;;:::i;:::-;;;;;;;;;194955:1;194942:11;:14;194934:40;;;;;;;;;;;;:::i;:::-;;;;;;;;;195013:11;194987:8;:12;194996:2;194987:12;;;;;;;;;;;:22;;;:37;;;;;;;:::i;:::-;;;;;;;;195058:2;195042:31;195061:11;195042:31;;;;;;:::i;:::-;;;;;;;;194787:294:::0;;:::o;142314:223::-;142438:36;142455:12;:10;:12::i;:::-;142469:4;142438:16;:36::i;:::-;142485:44;142503:4;142509:2;142513;142517:5;142524:4;142485:17;:44::i;:::-;142314:223;;;;;:::o;157514:220::-;156467:13;:11;:13::i;:::-;157619:1:::1;157599:22;;:8;:22;;::::0;157595:93:::1;;157673:1;157645:31;;;;;;;;;;;:::i;:::-;;;;;;;;157595:93;157698:28;157717:8;157698:18;:28::i;:::-;157514:220:::0;:::o;192201:34::-;192234:1;192201:34;:::o;188389:215::-;188491:4;188530:26;188515:41;;;:11;:41;;;;:81;;;;188560:36;188584:11;188560:23;:36::i;:::-;188515:81;188508:88;;188389:215;;;:::o;189597:97::-;189655:6;189681:5;189674:12;;189597:97;:::o;20115:98::-;20168:7;20195:10;20188:17;;20115:98;:::o;143028:239::-;143133:8;143124:17;;:5;:17;;;;:55;;;;;143146:33;143163:5;143170:8;143146:16;:33::i;:::-;143145:34;143124:55;143120:140;;;143232:8;143242:5;143203:45;;;;;;;;;;;;:::i;:::-;;;;;;;;143120:140;143028:239;;:::o;149064:465::-;149278:1;149264:16;;:2;:16;;;149260:90;;149335:1;149304:34;;;;;;;;;;;:::i;:::-;;;;;;;;149260:90;149380:1;149364:18;;:4;:18;;;149360:90;;149435:1;149406:32;;;;;;;;;;;:::i;:::-;;;;;;;;149360:90;149460:61;149487:4;149493:2;149497:3;149502:6;149510:4;149516;149460:26;:61::i;:::-;149064:465;;;;;:::o;156746:166::-;156817:12;:10;:12::i;:::-;156806:23;;:7;:5;:7::i;:::-;:23;;;156802:103;;156880:12;:10;:12::i;:::-;156853:40;;;;;;;;;;;:::i;:::-;;;;;;;;156802:103;156746:166::o;169657:208::-;169745:37;169759:5;169766:2;169770:5;169777:4;169745:13;:37::i;:::-;169740:118;;169839:5;169806:40;;;;;;;;;;;:::i;:::-;;;;;;;;169740:118;169657:208;;;:::o;160620:120::-;159629:16;:14;:16::i;:::-;160689:5:::1;160679:7;;:15;;;;;;;;;;;;;;;;;;160710:22;160719:12;:10;:12::i;:::-;160710:22;;;;;;:::i;:::-;;;;;;;;160620:120::o:0;159924:108::-;159995:8;:6;:8::i;:::-;159994:9;159986:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;159924:108::o;184427:293::-;183829:1;184561:7;;:19;184553:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;183829:1;184694:7;:18;;;;184427:293::o;170110:236::-;170216:47;170234:5;170241:4;170247:2;170251:5;170258:4;170216:17;:47::i;:::-;170211:128;;170320:5;170287:40;;;;;;;;;;;:::i;:::-;;;;;;;;170211:128;170110:236;;;;:::o;150851:359::-;150962:1;150948:16;;:2;:16;;;150944:90;;151019:1;150988:34;;;;;;;;;;;:::i;:::-;;;;;;;;150944:90;151045:20;151067:23;151094:29;151113:2;151117:5;151094:18;:29::i;:::-;151044:79;;;;151134:68;151169:1;151173:2;151177:3;151182:6;151190:4;151196:5;151134:26;:68::i;:::-;150933:277;;150851:359;;;;:::o;184728:213::-;183785:1;184911:7;:22;;;;184728:213::o;135222:201::-;135308:11;135398:4;135393:3;135389:14;135382:4;135377:3;135373:14;135369:35;135363:42;135356:49;;135222:201;;;;:::o;136042:::-;136128:11;136218:4;136213:3;136209:14;136202:4;136197:3;136193:14;136189:35;136183:42;136176:49;;136042:201;;;;:::o;157894:191::-;157968:16;157987:6;;;;;;;;;;;157968:25;;158013:8;158004:6;;:17;;;;;;;;;;;;;;;;;;158068:8;158037:40;;158058:8;158037:40;;;;;;;;;;;;157957:128;157894:191;:::o;160361:118::-;159370:19;:17;:19::i;:::-;160431:4:::1;160421:7;;:14;;;;;;;;;;;;;;;;;;160451:20;160458:12;:10;:12::i;:::-;160451:20;;;;;;:::i;:::-;;;;;;;;160361:118::o:0;189965:518::-;190060:19;190082:17;:15;:17::i;:::-;190060:39;;;;190129:11;190114:12;:26;;;190110:176;;;190248:12;190262:11;190219:55;;;;;;;;;;;;:::i;:::-;;;;;;;;190110:176;190320:1;190300:22;;:8;:22;;;190296:110;;190391:1;190346:48;;;;;;;;;;;:::i;:::-;;;;;;;;190296:110;190440:35;;;;;;;;190452:8;190440:35;;;;;;190462:12;190440:35;;;;;190418:19;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;190049:434;189965:518;;:::o;153517:424::-;153642:1;153625:19;;:5;:19;;;153621:93;;153699:1;153668:34;;;;;;;;;;;:::i;:::-;;;;;;;;153621:93;153748:1;153728:22;;:8;:22;;;153724:96;;153805:1;153774:34;;;;;;;;;;;:::i;:::-;;;;;;;;153724:96;153868:8;153830:18;:25;153849:5;153830:25;;;;;;;;;;;;;;;:35;153856:8;153830:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;153914:8;153892:41;;153907:5;153892:41;;;153924:8;153892:41;;;;;;:::i;:::-;;;;;;;;153517:424;;;:::o;148171:479::-;148308:1;148294:16;;:2;:16;;;148290:90;;148365:1;148334:34;;;;;;;;;;;:::i;:::-;;;;;;;;148290:90;148410:1;148394:18;;:4;:18;;;148390:90;;148465:1;148436:32;;;;;;;;;;;:::i;:::-;;;;;;;;148390:90;148491:20;148513:23;148540:29;148559:2;148563:5;148540:18;:29::i;:::-;148490:79;;;;148580:62;148607:4;148613:2;148617:3;148622:6;148630:4;148636:5;148580:26;:62::i;:::-;148279:371;;148171:479;;;;;:::o;140164:310::-;140266:4;140318:26;140303:41;;;:11;:41;;;;:110;;;;140376:37;140361:52;;;:11;:52;;;;140303:110;:163;;;;140430:36;140454:11;140430:23;:36::i;:::-;140303:163;140283:183;;140164:310;;;:::o;146971:729::-;147200:30;147208:4;147214:2;147218:3;147223:6;147200:7;:30::i;:::-;147259:1;147245:16;;:2;:16;;;147241:452;;147278:16;147297:12;:10;:12::i;:::-;147278:31;;147328:5;147324:358;;;147354:79;147395:8;147405:4;147411:2;147415:3;147420:6;147428:4;147354:40;:79::i;:::-;147324:358;;;147474:10;147487:25;147510:1;147487:3;:22;;:25;;;;:::i;:::-;147474:38;;147531:13;147547:28;147573:1;147547:6;:25;;:28;;;;:::i;:::-;147531:44;;147594:72;147630:8;147640:4;147646:2;147650;147654:5;147661:4;147594:35;:72::i;:::-;147455:227;;147324:358;147263:430;147241:452;146971:729;;;;;;:::o;176954:1268::-;177048:12;177073:15;177091:24;;;177073:42;;177185:4;177179:11;177217:8;177211:4;177204:22;177273:1;177269:6;177265:2;177261:15;177257:2;177253:24;177247:4;177240:38;177305:5;177299:4;177292:19;177376:4;177370;177364;177358;177355:1;177348:5;177341;177336:45;177325:56;;177596:1;177589:4;177583:11;177580:18;177571:7;177567:32;177557:616;;177730:6;177720:7;177713:15;177709:28;177706:168;;;177787:16;177781:4;177776:3;177761:43;177838:16;177833:3;177826:29;177706:168;178154:1;178146:5;178134:18;178131:25;178112:16;178105:24;178101:56;178092:7;178088:70;178077:81;;177557:616;178200:3;178194:4;178187:17;177153:1062;;176954:1268;;;;;;:::o;160109:108::-;160176:8;:6;:8::i;:::-;160168:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;160109:108::o;178782:1425::-;178946:12;178971:15;178989:28;;;178971:46;;179087:4;179081:11;179119:8;179113:4;179106:22;179177:1;179173:6;179169:2;179165:15;179159:4;179155:26;179149:4;179142:40;179229:1;179225:6;179221:2;179217:15;179213:2;179209:24;179203:4;179196:38;179261:5;179255:4;179248:19;179332:4;179326;179320;179314;179311:1;179304:5;179297;179292:45;179281:56;;179552:1;179545:4;179539:11;179536:18;179527:7;179523:32;179513:616;;179686:6;179676:7;179669:15;179665:28;179662:168;;;179743:16;179737:4;179732:3;179717:43;179794:16;179789:3;179782:29;179662:168;180110:1;180102:5;180090:18;180087:25;180068:16;180061:24;180057:56;180048:7;180044:70;180033:81;;179513:616;180156:3;180150:4;180143:17;180187:1;180181:4;180174:15;179055:1145;;178782:1425;;;;;;;:::o;154062:842::-;154173:23;154198;154335:4;154329:11;154319:21;;154407:1;154399:6;154392:17;154547:8;154540:4;154532:6;154528:17;154521:35;154672:4;154664:6;154660:17;154650:27;;154706:1;154698:6;154691:17;154748:8;154741:4;154733:6;154729:17;154722:35;154880:4;154872:6;154868:17;154862:4;154855:31;154062:842;;;;;:::o;21183:148::-;21259:4;21298:25;21283:40;;;:11;:40;;;;21276:47;;21183:148;;;:::o;143984:1315::-;144120:6;:13;144106:3;:10;:27;144102:119;;144183:3;:10;144195:6;:13;144157:52;;;;;;;;;;;;:::i;:::-;;;;;;;;144102:119;144233:16;144252:12;:10;:12::i;:::-;144233:31;;144282:9;144294:1;144282:13;;144277:709;144301:3;:10;144297:1;:14;144277:709;;;144333:10;144346:25;144369:1;144346:3;:22;;:25;;;;:::i;:::-;144333:38;;144386:13;144402:28;144428:1;144402:6;:25;;:28;;;;:::i;:::-;144386:44;;144467:1;144451:18;;:4;:18;;;144447:429;;144490:19;144512:9;:13;144522:2;144512:13;;;;;;;;;;;:19;144526:4;144512:19;;;;;;;;;;;;;;;;144490:41;;144568:5;144554:11;:19;144550:131;;;144632:4;144638:11;144651:5;144658:2;144605:56;;;;;;;;;;;;;;:::i;:::-;;;;;;;;144550:131;144836:5;144822:11;:19;144800:9;:13;144810:2;144800:13;;;;;;;;;;;:19;144814:4;144800:19;;;;;;;;;;;;;;;:41;;;;144471:405;144447:429;144910:1;144896:16;;:2;:16;;;144892:83;;144954:5;144933:9;:13;144943:2;144933:13;;;;;;;;;;;:17;144947:2;144933:17;;;;;;;;;;;;;;;;:26;;;;;;;:::i;:::-;;;;;;;;144892:83;144318:668;;144313:3;;;;;144277:709;;;;145016:1;145002:3;:10;:15;144998:294;;145034:10;145047:25;145070:1;145047:3;:22;;:25;;;;:::i;:::-;145034:38;;145087:13;145103:28;145129:1;145103:6;:25;;:28;;;;:::i;:::-;145087:44;;145182:2;145151:45;;145176:4;145151:45;;145166:8;145151:45;;;145186:2;145190:5;145151:45;;;;;;;:::i;:::-;;;;;;;;145019:189;;144998:294;;;145264:2;145234:46;;145258:4;145234:46;;145248:8;145234:46;;;145268:3;145273:6;145234:46;;;;;;;:::i;:::-;;;;;;;;144998:294;144091:1208;143984:1315;;;;:::o;18358:1055::-;18607:1;18590:2;:14;;;:18;18586:820;;;18646:2;18629:43;;;18673:8;18683:4;18689:3;18694:6;18702:4;18629:78;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;18625:770;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19066:1;19049:6;:13;:18;19045:335;;19194:2;19156:41;;;;;;;;;;;:::i;:::-;;;;;;;;19045:335;19330:6;19324:13;19317:4;19309:6;19305:17;19298:40;18625:770;18801:48;;;18789:60;;;:8;:60;;;;18785:197;;18959:2;18921:41;;;;;;;;;;;:::i;:::-;;;;;;;;18785:197;18708:289;18586:820;18358:1055;;;;;;:::o;16806:986::-;17030:1;17013:2;:14;;;:18;17009:776;;;17069:2;17052:38;;;17091:8;17101:4;17107:2;17111:5;17118:4;17052:71;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;17048:726;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17445:1;17428:6;:13;:18;17424:335;;17573:2;17535:41;;;;;;;;;;;:::i;:::-;;;;;;;;17424:335;17709:6;17703:13;17696:4;17688:6;17684:17;17677:40;17048:726;17185:43;;;17173:55;;;:8;:55;;;;17169:192;;17338:2;17300:41;;;;;;;;;;;:::i;:::-;;;;;;;;17169:192;17124:252;17009:776;16806:986;;;;;;:::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:126;371:7;411:42;404:5;400:54;389:65;;334:126;;;:::o;466:96::-;503:7;532:24;550:5;532:24;:::i;:::-;521:35;;466:96;;;:::o;568:122::-;641:24;659:5;641:24;:::i;:::-;634:5;631:35;621:63;;680:1;677;670:12;621:63;568:122;:::o;696:139::-;742:5;780:6;767:20;758:29;;796:33;823:5;796:33;:::i;:::-;696:139;;;;:::o;841:77::-;878:7;907:5;896:16;;841:77;;;:::o;924:122::-;997:24;1015:5;997:24;:::i;:::-;990:5;987:35;977:63;;1036:1;1033;1026:12;977:63;924:122;:::o;1052:139::-;1098:5;1136:6;1123:20;1114:29;;1152:33;1179:5;1152:33;:::i;:::-;1052:139;;;;:::o;1197:474::-;1265:6;1273;1322:2;1310:9;1301:7;1297:23;1293:32;1290:119;;;1328:79;;:::i;:::-;1290:119;1448:1;1473:53;1518:7;1509:6;1498:9;1494:22;1473:53;:::i;:::-;1463:63;;1419:117;1575:2;1601:53;1646:7;1637:6;1626:9;1622:22;1601:53;:::i;:::-;1591:63;;1546:118;1197:474;;;;;:::o;1677:118::-;1764:24;1782:5;1764:24;:::i;:::-;1759:3;1752:37;1677:118;;:::o;1801:222::-;1894:4;1932:2;1921:9;1917:18;1909:26;;1945:71;2013:1;2002:9;1998:17;1989:6;1945:71;:::i;:::-;1801:222;;;;:::o;2029:149::-;2065:7;2105:66;2098:5;2094:78;2083:89;;2029:149;;;:::o;2184:120::-;2256:23;2273:5;2256:23;:::i;:::-;2249:5;2246:34;2236:62;;2294:1;2291;2284:12;2236:62;2184:120;:::o;2310:137::-;2355:5;2393:6;2380:20;2371:29;;2409:32;2435:5;2409:32;:::i;:::-;2310:137;;;;:::o;2453:327::-;2511:6;2560:2;2548:9;2539:7;2535:23;2531:32;2528:119;;;2566:79;;:::i;:::-;2528:119;2686:1;2711:52;2755:7;2746:6;2735:9;2731:22;2711:52;:::i;:::-;2701:62;;2657:116;2453:327;;;;:::o;2786:90::-;2820:7;2863:5;2856:13;2849:21;2838:32;;2786:90;;;:::o;2882:109::-;2963:21;2978:5;2963:21;:::i;:::-;2958:3;2951:34;2882:109;;:::o;2997:210::-;3084:4;3122:2;3111:9;3107:18;3099:26;;3135:65;3197:1;3186:9;3182:17;3173:6;3135:65;:::i;:::-;2997:210;;;;:::o;3213:99::-;3265:6;3299:5;3293:12;3283:22;;3213:99;;;:::o;3318:169::-;3402:11;3436:6;3431:3;3424:19;3476:4;3471:3;3467:14;3452:29;;3318:169;;;;:::o;3493:139::-;3582:6;3577:3;3572;3566:23;3623:1;3614:6;3609:3;3605:16;3598:27;3493:139;;;:::o;3638:102::-;3679:6;3730:2;3726:7;3721:2;3714:5;3710:14;3706:28;3696:38;;3638:102;;;:::o;3746:377::-;3834:3;3862:39;3895:5;3862:39;:::i;:::-;3917:71;3981:6;3976:3;3917:71;:::i;:::-;3910:78;;3997:65;4055:6;4050:3;4043:4;4036:5;4032:16;3997:65;:::i;:::-;4087:29;4109:6;4087:29;:::i;:::-;4082:3;4078:39;4071:46;;3838:285;3746:377;;;;:::o;4129:313::-;4242:4;4280:2;4269:9;4265:18;4257:26;;4329:9;4323:4;4319:20;4315:1;4304:9;4300:17;4293:47;4357:78;4430:4;4421:6;4357:78;:::i;:::-;4349:86;;4129:313;;;;:::o;4448:329::-;4507:6;4556:2;4544:9;4535:7;4531:23;4527:32;4524:119;;;4562:79;;:::i;:::-;4524:119;4682:1;4707:53;4752:7;4743:6;4732:9;4728:22;4707:53;:::i;:::-;4697:63;;4653:117;4448:329;;;;:::o;4783:474::-;4851:6;4859;4908:2;4896:9;4887:7;4883:23;4879:32;4876:119;;;4914:79;;:::i;:::-;4876:119;5034:1;5059:53;5104:7;5095:6;5084:9;5080:22;5059:53;:::i;:::-;5049:63;;5005:117;5161:2;5187:53;5232:7;5223:6;5212:9;5208:22;5187:53;:::i;:::-;5177:63;;5132:118;4783:474;;;;;:::o;5263:::-;5331:6;5339;5388:2;5376:9;5367:7;5363:23;5359:32;5356:119;;;5394:79;;:::i;:::-;5356:119;5514:1;5539:53;5584:7;5575:6;5564:9;5560:22;5539:53;:::i;:::-;5529:63;;5485:117;5641:2;5667:53;5712:7;5703:6;5692:9;5688:22;5667:53;:::i;:::-;5657:63;;5612:118;5263:474;;;;;:::o;5743:118::-;5830:24;5848:5;5830:24;:::i;:::-;5825:3;5818:37;5743:118;;:::o;5867:332::-;5988:4;6026:2;6015:9;6011:18;6003:26;;6039:71;6107:1;6096:9;6092:17;6083:6;6039:71;:::i;:::-;6120:72;6188:2;6177:9;6173:18;6164:6;6120:72;:::i;:::-;5867:332;;;;;:::o;6205:117::-;6314:1;6311;6304:12;6328:180;6376:77;6373:1;6366:88;6473:4;6470:1;6463:15;6497:4;6494:1;6487:15;6514:281;6597:27;6619:4;6597:27;:::i;:::-;6589:6;6585:40;6727:6;6715:10;6712:22;6691:18;6679:10;6676:34;6673:62;6670:88;;;6738:18;;:::i;:::-;6670:88;6778:10;6774:2;6767:22;6557:238;6514:281;;:::o;6801:129::-;6835:6;6862:20;;:::i;:::-;6852:30;;6891:33;6919:4;6911:6;6891:33;:::i;:::-;6801:129;;;:::o;6936:311::-;7013:4;7103:18;7095:6;7092:30;7089:56;;;7125:18;;:::i;:::-;7089:56;7175:4;7167:6;7163:17;7155:25;;7235:4;7229;7225:15;7217:23;;6936:311;;;:::o;7253:117::-;7362:1;7359;7352:12;7393:710;7489:5;7514:81;7530:64;7587:6;7530:64;:::i;:::-;7514:81;:::i;:::-;7505:90;;7615:5;7644:6;7637:5;7630:21;7678:4;7671:5;7667:16;7660:23;;7731:4;7723:6;7719:17;7711:6;7707:30;7760:3;7752:6;7749:15;7746:122;;;7779:79;;:::i;:::-;7746:122;7894:6;7877:220;7911:6;7906:3;7903:15;7877:220;;;7986:3;8015:37;8048:3;8036:10;8015:37;:::i;:::-;8010:3;8003:50;8082:4;8077:3;8073:14;8066:21;;7953:144;7937:4;7932:3;7928:14;7921:21;;7877:220;;;7881:21;7495:608;;7393:710;;;;;:::o;8126:370::-;8197:5;8246:3;8239:4;8231:6;8227:17;8223:27;8213:122;;8254:79;;:::i;:::-;8213:122;8371:6;8358:20;8396:94;8486:3;8478:6;8471:4;8463:6;8459:17;8396:94;:::i;:::-;8387:103;;8203:293;8126:370;;;;:::o;8502:117::-;8611:1;8608;8601:12;8625:307;8686:4;8776:18;8768:6;8765:30;8762:56;;;8798:18;;:::i;:::-;8762:56;8836:29;8858:6;8836:29;:::i;:::-;8828:37;;8920:4;8914;8910:15;8902:23;;8625:307;;;:::o;8938:148::-;9036:6;9031:3;9026;9013:30;9077:1;9068:6;9063:3;9059:16;9052:27;8938:148;;;:::o;9092:423::-;9169:5;9194:65;9210:48;9251:6;9210:48;:::i;:::-;9194:65;:::i;:::-;9185:74;;9282:6;9275:5;9268:21;9320:4;9313:5;9309:16;9358:3;9349:6;9344:3;9340:16;9337:25;9334:112;;;9365:79;;:::i;:::-;9334:112;9455:54;9502:6;9497:3;9492;9455:54;:::i;:::-;9175:340;9092:423;;;;;:::o;9534:338::-;9589:5;9638:3;9631:4;9623:6;9619:17;9615:27;9605:122;;9646:79;;:::i;:::-;9605:122;9763:6;9750:20;9788:78;9862:3;9854:6;9847:4;9839:6;9835:17;9788:78;:::i;:::-;9779:87;;9595:277;9534:338;;;;:::o;9878:1509::-;10032:6;10040;10048;10056;10064;10113:3;10101:9;10092:7;10088:23;10084:33;10081:120;;;10120:79;;:::i;:::-;10081:120;10240:1;10265:53;10310:7;10301:6;10290:9;10286:22;10265:53;:::i;:::-;10255:63;;10211:117;10367:2;10393:53;10438:7;10429:6;10418:9;10414:22;10393:53;:::i;:::-;10383:63;;10338:118;10523:2;10512:9;10508:18;10495:32;10554:18;10546:6;10543:30;10540:117;;;10576:79;;:::i;:::-;10540:117;10681:78;10751:7;10742:6;10731:9;10727:22;10681:78;:::i;:::-;10671:88;;10466:303;10836:2;10825:9;10821:18;10808:32;10867:18;10859:6;10856:30;10853:117;;;10889:79;;:::i;:::-;10853:117;10994:78;11064:7;11055:6;11044:9;11040:22;10994:78;:::i;:::-;10984:88;;10779:303;11149:3;11138:9;11134:19;11121:33;11181:18;11173:6;11170:30;11167:117;;;11203:79;;:::i;:::-;11167:117;11308:62;11362:7;11353:6;11342:9;11338:22;11308:62;:::i;:::-;11298:72;;11092:288;9878:1509;;;;;;;;:::o;11393:474::-;11461:6;11469;11518:2;11506:9;11497:7;11493:23;11489:32;11486:119;;;11524:79;;:::i;:::-;11486:119;11644:1;11669:53;11714:7;11705:6;11694:9;11690:22;11669:53;:::i;:::-;11659:63;;11615:117;11771:2;11797:53;11842:7;11833:6;11822:9;11818:22;11797:53;:::i;:::-;11787:63;;11742:118;11393:474;;;;;:::o;11873:541::-;12044:4;12082:3;12071:9;12067:19;12059:27;;12096:71;12164:1;12153:9;12149:17;12140:6;12096:71;:::i;:::-;12177:72;12245:2;12234:9;12230:18;12221:6;12177:72;:::i;:::-;12259:66;12321:2;12310:9;12306:18;12297:6;12259:66;:::i;:::-;12335:72;12403:2;12392:9;12388:18;12379:6;12335:72;:::i;:::-;11873:541;;;;;;;:::o;12420:619::-;12497:6;12505;12513;12562:2;12550:9;12541:7;12537:23;12533:32;12530:119;;;12568:79;;:::i;:::-;12530:119;12688:1;12713:53;12758:7;12749:6;12738:9;12734:22;12713:53;:::i;:::-;12703:63;;12659:117;12815:2;12841:53;12886:7;12877:6;12866:9;12862:22;12841:53;:::i;:::-;12831:63;;12786:118;12943:2;12969:53;13014:7;13005:6;12994:9;12990:22;12969:53;:::i;:::-;12959:63;;12914:118;12420:619;;;;;:::o;13045:116::-;13115:21;13130:5;13115:21;:::i;:::-;13108:5;13105:32;13095:60;;13151:1;13148;13141:12;13095:60;13045:116;:::o;13167:133::-;13210:5;13248:6;13235:20;13226:29;;13264:30;13288:5;13264:30;:::i;:::-;13167:133;;;;:::o;13306:468::-;13371:6;13379;13428:2;13416:9;13407:7;13403:23;13399:32;13396:119;;;13434:79;;:::i;:::-;13396:119;13554:1;13579:53;13624:7;13615:6;13604:9;13600:22;13579:53;:::i;:::-;13569:63;;13525:117;13681:2;13707:50;13749:7;13740:6;13729:9;13725:22;13707:50;:::i;:::-;13697:60;;13652:115;13306:468;;;;;:::o;13780:311::-;13857:4;13947:18;13939:6;13936:30;13933:56;;;13969:18;;:::i;:::-;13933:56;14019:4;14011:6;14007:17;13999:25;;14079:4;14073;14069:15;14061:23;;13780:311;;;:::o;14114:710::-;14210:5;14235:81;14251:64;14308:6;14251:64;:::i;:::-;14235:81;:::i;:::-;14226:90;;14336:5;14365:6;14358:5;14351:21;14399:4;14392:5;14388:16;14381:23;;14452:4;14444:6;14440:17;14432:6;14428:30;14481:3;14473:6;14470:15;14467:122;;;14500:79;;:::i;:::-;14467:122;14615:6;14598:220;14632:6;14627:3;14624:15;14598:220;;;14707:3;14736:37;14769:3;14757:10;14736:37;:::i;:::-;14731:3;14724:50;14803:4;14798:3;14794:14;14787:21;;14674:144;14658:4;14653:3;14649:14;14642:21;;14598:220;;;14602:21;14216:608;;14114:710;;;;;:::o;14847:370::-;14918:5;14967:3;14960:4;14952:6;14948:17;14944:27;14934:122;;14975:79;;:::i;:::-;14934:122;15092:6;15079:20;15117:94;15207:3;15199:6;15192:4;15184:6;15180:17;15117:94;:::i;:::-;15108:103;;14924:293;14847:370;;;;:::o;15223:894::-;15341:6;15349;15398:2;15386:9;15377:7;15373:23;15369:32;15366:119;;;15404:79;;:::i;:::-;15366:119;15552:1;15541:9;15537:17;15524:31;15582:18;15574:6;15571:30;15568:117;;;15604:79;;:::i;:::-;15568:117;15709:78;15779:7;15770:6;15759:9;15755:22;15709:78;:::i;:::-;15699:88;;15495:302;15864:2;15853:9;15849:18;15836:32;15895:18;15887:6;15884:30;15881:117;;;15917:79;;:::i;:::-;15881:117;16022:78;16092:7;16083:6;16072:9;16068:22;16022:78;:::i;:::-;16012:88;;15807:303;15223:894;;;;;:::o;16123:114::-;16190:6;16224:5;16218:12;16208:22;;16123:114;;;:::o;16243:184::-;16342:11;16376:6;16371:3;16364:19;16416:4;16411:3;16407:14;16392:29;;16243:184;;;;:::o;16433:132::-;16500:4;16523:3;16515:11;;16553:4;16548:3;16544:14;16536:22;;16433:132;;;:::o;16571:108::-;16648:24;16666:5;16648:24;:::i;:::-;16643:3;16636:37;16571:108;;:::o;16685:179::-;16754:10;16775:46;16817:3;16809:6;16775:46;:::i;:::-;16853:4;16848:3;16844:14;16830:28;;16685:179;;;;:::o;16870:113::-;16940:4;16972;16967:3;16963:14;16955:22;;16870:113;;;:::o;17019:732::-;17138:3;17167:54;17215:5;17167:54;:::i;:::-;17237:86;17316:6;17311:3;17237:86;:::i;:::-;17230:93;;17347:56;17397:5;17347:56;:::i;:::-;17426:7;17457:1;17442:284;17467:6;17464:1;17461:13;17442:284;;;17543:6;17537:13;17570:63;17629:3;17614:13;17570:63;:::i;:::-;17563:70;;17656:60;17709:6;17656:60;:::i;:::-;17646:70;;17502:224;17489:1;17486;17482:9;17477:14;;17442:284;;;17446:14;17742:3;17735:10;;17143:608;;;17019:732;;;;:::o;17757:373::-;17900:4;17938:2;17927:9;17923:18;17915:26;;17987:9;17981:4;17977:20;17973:1;17962:9;17958:17;17951:47;18015:108;18118:4;18109:6;18015:108;:::i;:::-;18007:116;;17757:373;;;;:::o;18136:117::-;18245:1;18242;18235:12;18273:553;18331:8;18341:6;18391:3;18384:4;18376:6;18372:17;18368:27;18358:122;;18399:79;;:::i;:::-;18358:122;18512:6;18499:20;18489:30;;18542:18;18534:6;18531:30;18528:117;;;18564:79;;:::i;:::-;18528:117;18678:4;18670:6;18666:17;18654:29;;18732:3;18724:4;18716:6;18712:17;18702:8;18698:32;18695:41;18692:128;;;18739:79;;:::i;:::-;18692:128;18273:553;;;;;:::o;18832:674::-;18912:6;18920;18928;18977:2;18965:9;18956:7;18952:23;18948:32;18945:119;;;18983:79;;:::i;:::-;18945:119;19103:1;19128:53;19173:7;19164:6;19153:9;19149:22;19128:53;:::i;:::-;19118:63;;19074:117;19258:2;19247:9;19243:18;19230:32;19289:18;19281:6;19278:30;19275:117;;;19311:79;;:::i;:::-;19275:117;19424:65;19481:7;19472:6;19461:9;19457:22;19424:65;:::i;:::-;19406:83;;;;19201:298;18832:674;;;;;:::o;19512:329::-;19571:6;19620:2;19608:9;19599:7;19595:23;19591:32;19588:119;;;19626:79;;:::i;:::-;19588:119;19746:1;19771:53;19816:7;19807:6;19796:9;19792:22;19771:53;:::i;:::-;19761:63;;19717:117;19512:329;;;;:::o;19847:430::-;19990:4;20028:2;20017:9;20013:18;20005:26;;20041:71;20109:1;20098:9;20094:17;20085:6;20041:71;:::i;:::-;20122:72;20190:2;20179:9;20175:18;20166:6;20122:72;:::i;:::-;20204:66;20266:2;20255:9;20251:18;20242:6;20204:66;:::i;:::-;19847:430;;;;;;:::o;20283:332::-;20404:4;20442:2;20431:9;20427:18;20419:26;;20455:71;20523:1;20512:9;20508:17;20499:6;20455:71;:::i;:::-;20536:72;20604:2;20593:9;20589:18;20580:6;20536:72;:::i;:::-;20283:332;;;;;:::o;20621:222::-;20714:4;20752:2;20741:9;20737:18;20729:26;;20765:71;20833:1;20822:9;20818:17;20809:6;20765:71;:::i;:::-;20621:222;;;;:::o;20849:109::-;20885:7;20925:26;20918:5;20914:38;20903:49;;20849:109;;;:::o;20964:120::-;21036:23;21053:5;21036:23;:::i;:::-;21029:5;21026:34;21016:62;;21074:1;21071;21064:12;21016:62;20964:120;:::o;21090:137::-;21135:5;21173:6;21160:20;21151:29;;21189:32;21215:5;21189:32;:::i;:::-;21090:137;;;;:::o;21233:472::-;21300:6;21308;21357:2;21345:9;21336:7;21332:23;21328:32;21325:119;;;21363:79;;:::i;:::-;21325:119;21483:1;21508:53;21553:7;21544:6;21533:9;21529:22;21508:53;:::i;:::-;21498:63;;21454:117;21610:2;21636:52;21680:7;21671:6;21660:9;21656:22;21636:52;:::i;:::-;21626:62;;21581:117;21233:472;;;;;:::o;21711:619::-;21788:6;21796;21804;21853:2;21841:9;21832:7;21828:23;21824:32;21821:119;;;21859:79;;:::i;:::-;21821:119;21979:1;22004:53;22049:7;22040:6;22029:9;22025:22;22004:53;:::i;:::-;21994:63;;21950:117;22106:2;22132:53;22177:7;22168:6;22157:9;22153:22;22132:53;:::i;:::-;22122:63;;22077:118;22234:2;22260:53;22305:7;22296:6;22285:9;22281:22;22260:53;:::i;:::-;22250:63;;22205:118;21711:619;;;;;:::o;22336:613::-;22410:6;22418;22426;22475:2;22463:9;22454:7;22450:23;22446:32;22443:119;;;22481:79;;:::i;:::-;22443:119;22601:1;22626:53;22671:7;22662:6;22651:9;22647:22;22626:53;:::i;:::-;22616:63;;22572:117;22728:2;22754:53;22799:7;22790:6;22779:9;22775:22;22754:53;:::i;:::-;22744:63;;22699:118;22856:2;22882:50;22924:7;22915:6;22904:9;22900:22;22882:50;:::i;:::-;22872:60;;22827:115;22336:613;;;;;:::o;22955:323::-;23011:6;23060:2;23048:9;23039:7;23035:23;23031:32;23028:119;;;23066:79;;:::i;:::-;23028:119;23186:1;23211:50;23253:7;23244:6;23233:9;23229:22;23211:50;:::i;:::-;23201:60;;23157:114;22955:323;;;;:::o;23284:1089::-;23388:6;23396;23404;23412;23420;23469:3;23457:9;23448:7;23444:23;23440:33;23437:120;;;23476:79;;:::i;:::-;23437:120;23596:1;23621:53;23666:7;23657:6;23646:9;23642:22;23621:53;:::i;:::-;23611:63;;23567:117;23723:2;23749:53;23794:7;23785:6;23774:9;23770:22;23749:53;:::i;:::-;23739:63;;23694:118;23851:2;23877:53;23922:7;23913:6;23902:9;23898:22;23877:53;:::i;:::-;23867:63;;23822:118;23979:2;24005:53;24050:7;24041:6;24030:9;24026:22;24005:53;:::i;:::-;23995:63;;23950:118;24135:3;24124:9;24120:19;24107:33;24167:18;24159:6;24156:30;24153:117;;;24189:79;;:::i;:::-;24153:117;24294:62;24348:7;24339:6;24328:9;24324:22;24294:62;:::i;:::-;24284:72;;24078:288;23284:1089;;;;;;;;:::o;24379:180::-;24427:77;24424:1;24417:88;24524:4;24521:1;24514:15;24548:4;24545:1;24538:15;24565:320;24609:6;24646:1;24640:4;24636:12;24626:22;;24693:1;24687:4;24683:12;24714:18;24704:81;;24770:4;24762:6;24758:17;24748:27;;24704:81;24832:2;24824:6;24821:14;24801:18;24798:38;24795:84;;24851:18;;:::i;:::-;24795:84;24616:269;24565:320;;;:::o;24891:162::-;25031:14;25027:1;25019:6;25015:14;25008:38;24891:162;:::o;25059:366::-;25201:3;25222:67;25286:2;25281:3;25222:67;:::i;:::-;25215:74;;25298:93;25387:3;25298:93;:::i;:::-;25416:2;25411:3;25407:12;25400:19;;25059:366;;;:::o;25431:419::-;25597:4;25635:2;25624:9;25620:18;25612:26;;25684:9;25678:4;25674:20;25670:1;25659:9;25655:17;25648:47;25712:131;25838:4;25712:131;:::i;:::-;25704:139;;25431:419;;;:::o;25856:180::-;25904:77;25901:1;25894:88;26001:4;25998:1;25991:15;26025:4;26022:1;26015:15;26042:410;26082:7;26105:20;26123:1;26105:20;:::i;:::-;26100:25;;26139:20;26157:1;26139:20;:::i;:::-;26134:25;;26194:1;26191;26187:9;26216:30;26234:11;26216:30;:::i;:::-;26205:41;;26395:1;26386:7;26382:15;26379:1;26376:22;26356:1;26349:9;26329:83;26306:139;;26425:18;;:::i;:::-;26306:139;26090:362;26042:410;;;;:::o;26458:180::-;26506:77;26503:1;26496:88;26603:4;26600:1;26593:15;26627:4;26624:1;26617:15;26644:185;26684:1;26701:20;26719:1;26701:20;:::i;:::-;26696:25;;26735:20;26753:1;26735:20;:::i;:::-;26730:25;;26774:1;26764:35;;26779:18;;:::i;:::-;26764:35;26821:1;26818;26814:9;26809:14;;26644:185;;;;:::o;26835:143::-;26892:5;26923:6;26917:13;26908:22;;26939:33;26966:5;26939:33;:::i;:::-;26835:143;;;;:::o;26984:351::-;27054:6;27103:2;27091:9;27082:7;27078:23;27074:32;27071:119;;;27109:79;;:::i;:::-;27071:119;27229:1;27254:64;27310:7;27301:6;27290:9;27286:22;27254:64;:::i;:::-;27244:74;;27200:128;26984:351;;;;:::o;27341:194::-;27381:4;27401:20;27419:1;27401:20;:::i;:::-;27396:25;;27435:20;27453:1;27435:20;:::i;:::-;27430:25;;27479:1;27476;27472:9;27464:17;;27503:1;27497:4;27494:11;27491:37;;;27508:18;;:::i;:::-;27491:37;27341:194;;;;:::o;27541:164::-;27681:16;27677:1;27669:6;27665:14;27658:40;27541:164;:::o;27711:366::-;27853:3;27874:67;27938:2;27933:3;27874:67;:::i;:::-;27867:74;;27950:93;28039:3;27950:93;:::i;:::-;28068:2;28063:3;28059:12;28052:19;;27711:366;;;:::o;28083:419::-;28249:4;28287:2;28276:9;28272:18;28264:26;;28336:9;28330:4;28326:20;28322:1;28311:9;28307:17;28300:47;28364:131;28490:4;28364:131;:::i;:::-;28356:139;;28083:419;;;:::o;28508:167::-;28648:19;28644:1;28636:6;28632:14;28625:43;28508:167;:::o;28681:366::-;28823:3;28844:67;28908:2;28903:3;28844:67;:::i;:::-;28837:74;;28920:93;29009:3;28920:93;:::i;:::-;29038:2;29033:3;29029:12;29022:19;;28681:366;;;:::o;29053:419::-;29219:4;29257:2;29246:9;29242:18;29234:26;;29306:9;29300:4;29296:20;29292:1;29281:9;29277:17;29270:47;29334:131;29460:4;29334:131;:::i;:::-;29326:139;;29053:419;;;:::o;29478:163::-;29618:15;29614:1;29606:6;29602:14;29595:39;29478:163;:::o;29647:366::-;29789:3;29810:67;29874:2;29869:3;29810:67;:::i;:::-;29803:74;;29886:93;29975:3;29886:93;:::i;:::-;30004:2;29999:3;29995:12;29988:19;;29647:366;;;:::o;30019:419::-;30185:4;30223:2;30212:9;30208:18;30200:26;;30272:9;30266:4;30262:20;30258:1;30247:9;30243:17;30236:47;30300:131;30426:4;30300:131;:::i;:::-;30292:139;;30019:419;;;:::o;30444:191::-;30484:3;30503:20;30521:1;30503:20;:::i;:::-;30498:25;;30537:20;30555:1;30537:20;:::i;:::-;30532:25;;30580:1;30577;30573:9;30566:16;;30601:3;30598:1;30595:10;30592:36;;;30608:18;;:::i;:::-;30592:36;30444:191;;;;:::o;30641:158::-;30781:10;30777:1;30769:6;30765:14;30758:34;30641:158;:::o;30805:365::-;30947:3;30968:66;31032:1;31027:3;30968:66;:::i;:::-;30961:73;;31043:93;31132:3;31043:93;:::i;:::-;31161:2;31156:3;31152:12;31145:19;;30805:365;;;:::o;31176:419::-;31342:4;31380:2;31369:9;31365:18;31357:26;;31429:9;31423:4;31419:20;31415:1;31404:9;31400:17;31393:47;31457:131;31583:4;31457:131;:::i;:::-;31449:139;;31176:419;;;:::o;31601:165::-;31741:17;31737:1;31729:6;31725:14;31718:41;31601:165;:::o;31772:366::-;31914:3;31935:67;31999:2;31994:3;31935:67;:::i;:::-;31928:74;;32011:93;32100:3;32011:93;:::i;:::-;32129:2;32124:3;32120:12;32113:19;;31772:366;;;:::o;32144:419::-;32310:4;32348:2;32337:9;32333:18;32325:26;;32397:9;32391:4;32387:20;32383:1;32372:9;32368:17;32361:47;32425:131;32551:4;32425:131;:::i;:::-;32417:139;;32144:419;;;:::o;32569:233::-;32608:3;32631:24;32649:5;32631:24;:::i;:::-;32622:33;;32677:66;32670:5;32667:77;32664:103;;32747:18;;:::i;:::-;32664:103;32794:1;32787:5;32783:13;32776:20;;32569:233;;;:::o;32808:165::-;32948:17;32944:1;32936:6;32932:14;32925:41;32808:165;:::o;32979:366::-;33121:3;33142:67;33206:2;33201:3;33142:67;:::i;:::-;33135:74;;33218:93;33307:3;33218:93;:::i;:::-;33336:2;33331:3;33327:12;33320:19;;32979:366;;;:::o;33351:419::-;33517:4;33555:2;33544:9;33540:18;33532:26;;33604:9;33598:4;33594:20;33590:1;33579:9;33575:17;33568:47;33632:131;33758:4;33632:131;:::i;:::-;33624:139;;33351:419;;;:::o;33776:165::-;33916:17;33912:1;33904:6;33900:14;33893:41;33776:165;:::o;33947:366::-;34089:3;34110:67;34174:2;34169:3;34110:67;:::i;:::-;34103:74;;34186:93;34275:3;34186:93;:::i;:::-;34304:2;34299:3;34295:12;34288:19;;33947:366;;;:::o;34319:419::-;34485:4;34523:2;34512:9;34508:18;34500:26;;34572:9;34566:4;34562:20;34558:1;34547:9;34543:17;34536:47;34600:131;34726:4;34600:131;:::i;:::-;34592:139;;34319:419;;;:::o;34744:162::-;34884:14;34880:1;34872:6;34868:14;34861:38;34744:162;:::o;34912:366::-;35054:3;35075:67;35139:2;35134:3;35075:67;:::i;:::-;35068:74;;35151:93;35240:3;35151:93;:::i;:::-;35269:2;35264:3;35260:12;35253:19;;34912:366;;;:::o;35284:419::-;35450:4;35488:2;35477:9;35473:18;35465:26;;35537:9;35531:4;35527:20;35523:1;35512:9;35508:17;35501:47;35565:131;35691:4;35565:131;:::i;:::-;35557:139;;35284:419;;;:::o;35709:180::-;35757:77;35754:1;35747:88;35854:4;35851:1;35844:15;35878:4;35875:1;35868:15;35895:97;35954:6;35982:3;35972:13;;35895:97;;;;:::o;35998:141::-;36047:4;36070:3;36062:11;;36093:3;36090:1;36083:14;36127:4;36124:1;36114:18;36106:26;;35998:141;;;:::o;36145:93::-;36182:6;36229:2;36224;36217:5;36213:14;36209:23;36199:33;;36145:93;;;:::o;36244:107::-;36288:8;36338:5;36332:4;36328:16;36307:37;;36244:107;;;;:::o;36357:393::-;36426:6;36476:1;36464:10;36460:18;36499:97;36529:66;36518:9;36499:97;:::i;:::-;36617:39;36647:8;36636:9;36617:39;:::i;:::-;36605:51;;36689:4;36685:9;36678:5;36674:21;36665:30;;36738:4;36728:8;36724:19;36717:5;36714:30;36704:40;;36433:317;;36357:393;;;;;:::o;36756:60::-;36784:3;36805:5;36798:12;;36756:60;;;:::o;36822:142::-;36872:9;36905:53;36923:34;36932:24;36950:5;36932:24;:::i;:::-;36923:34;:::i;:::-;36905:53;:::i;:::-;36892:66;;36822:142;;;:::o;36970:75::-;37013:3;37034:5;37027:12;;36970:75;;;:::o;37051:269::-;37161:39;37192:7;37161:39;:::i;:::-;37222:91;37271:41;37295:16;37271:41;:::i;:::-;37263:6;37256:4;37250:11;37222:91;:::i;:::-;37216:4;37209:105;37127:193;37051:269;;;:::o;37326:73::-;37371:3;37392:1;37385:8;;37326:73;:::o;37405:189::-;37482:32;;:::i;:::-;37523:65;37581:6;37573;37567:4;37523:65;:::i;:::-;37458:136;37405:189;;:::o;37600:214::-;37685:1;37670:138;37695:9;37692:1;37689:16;37670:138;;;37747:51;37796:1;37792;37781:9;37777:17;37747:51;:::i;:::-;37720:1;37717;37713:9;37708:14;;37670:138;;;37674:14;37600:214;;:::o;37820:746::-;37921:2;37916:3;37913:11;37910:649;;;37950:10;37945:3;37942:19;37939:610;;;37996:38;38028:5;37996:38;:::i;:::-;38071:22;38089:3;38071:22;:::i;:::-;38130:29;38148:10;38130:29;:::i;:::-;38320:2;38308:10;38305:18;38302:79;;;38362:1;38346:17;;38302:79;38431:12;38421:8;38417:27;38461:74;38521:12;38507;38503:31;38490:11;38461:74;:::i;:::-;37962:587;;;;37939:610;37910:649;37820:746;;;:::o;38572:117::-;38626:8;38676:5;38670:4;38666:16;38645:37;;38572:117;;;;:::o;38695:169::-;38739:6;38772:51;38820:1;38816:6;38808:5;38805:1;38801:13;38772:51;:::i;:::-;38768:56;38853:4;38847;38843:15;38833:25;;38746:118;38695:169;;;;:::o;38869:295::-;38945:4;39091:29;39116:3;39110:4;39091:29;:::i;:::-;39083:37;;39153:3;39150:1;39146:11;39140:4;39137:21;39129:29;;38869:295;;;;:::o;39169:1403::-;39293:44;39333:3;39328;39293:44;:::i;:::-;39402:18;39394:6;39391:30;39388:56;;;39424:18;;:::i;:::-;39388:56;39468:38;39500:4;39494:11;39468:38;:::i;:::-;39553:67;39613:6;39605;39599:4;39553:67;:::i;:::-;39647:1;39676:2;39668:6;39665:14;39693:1;39688:632;;;;40364:1;40381:6;40378:84;;;40437:9;40432:3;40428:19;40415:33;40406:42;;40378:84;40488:67;40548:6;40541:5;40488:67;:::i;:::-;40482:4;40475:81;40337:229;39658:908;;39688:632;39740:4;39736:9;39728:6;39724:22;39774:37;39806:4;39774:37;:::i;:::-;39833:1;39847:215;39861:7;39858:1;39855:14;39847:215;;;39947:9;39942:3;39938:19;39925:33;39917:6;39910:49;39998:1;39990:6;39986:14;39976:24;;40045:2;40034:9;40030:18;40017:31;;39884:4;39881:1;39877:12;39872:17;;39847:215;;;40090:6;40081:7;40078:19;40075:186;;;40155:9;40150:3;40146:19;40133:33;40198:48;40240:4;40232:6;40228:17;40217:9;40198:48;:::i;:::-;40190:6;40183:64;40098:163;40075:186;40307:1;40303;40295:6;40291:14;40287:22;40281:4;40274:36;39695:625;;;39658:908;;39268:1304;;;39169:1403;;;:::o;40602:317::-;40700:3;40721:71;40785:6;40780:3;40721:71;:::i;:::-;40714:78;;40802:56;40851:6;40846:3;40839:5;40802:56;:::i;:::-;40883:29;40905:6;40883:29;:::i;:::-;40878:3;40874:39;40867:46;;40602:317;;;;;:::o;40925:333::-;41048:4;41086:2;41075:9;41071:18;41063:26;;41135:9;41129:4;41125:20;41121:1;41110:9;41106:17;41099:47;41163:88;41246:4;41237:6;41229;41163:88;:::i;:::-;41155:96;;40925:333;;;;;:::o;41264:115::-;41349:23;41366:5;41349:23;:::i;:::-;41344:3;41337:36;41264:115;;:::o;41385:218::-;41476:4;41514:2;41503:9;41499:18;41491:26;;41527:69;41593:1;41582:9;41578:17;41569:6;41527:69;:::i;:::-;41385:218;;;;:::o;41609:162::-;41749:14;41745:1;41737:6;41733:14;41726:38;41609:162;:::o;41777:366::-;41919:3;41940:67;42004:2;41999:3;41940:67;:::i;:::-;41933:74;;42016:93;42105:3;42016:93;:::i;:::-;42134:2;42129:3;42125:12;42118:19;;41777:366;;;:::o;42149:419::-;42315:4;42353:2;42342:9;42338:18;42330:26;;42402:9;42396:4;42392:20;42388:1;42377:9;42373:17;42366:47;42430:131;42556:4;42430:131;:::i;:::-;42422:139;;42149:419;;;:::o;42574:320::-;42689:4;42727:2;42716:9;42712:18;42704:26;;42740:71;42808:1;42797:9;42793:17;42784:6;42740:71;:::i;:::-;42821:66;42883:2;42872:9;42868:18;42859:6;42821:66;:::i;:::-;42574:320;;;;;:::o;42900:164::-;43040:16;43036:1;43028:6;43024:14;43017:40;42900:164;:::o;43070:366::-;43212:3;43233:67;43297:2;43292:3;43233:67;:::i;:::-;43226:74;;43309:93;43398:3;43309:93;:::i;:::-;43427:2;43422:3;43418:12;43411:19;;43070:366;;;:::o;43442:419::-;43608:4;43646:2;43635:9;43631:18;43623:26;;43695:9;43689:4;43685:20;43681:1;43670:9;43666:17;43659:47;43723:131;43849:4;43723:131;:::i;:::-;43715:139;;43442:419;;;:::o;43867:332::-;43988:4;44026:2;44015:9;44011:18;44003:26;;44039:71;44107:1;44096:9;44092:17;44083:6;44039:71;:::i;:::-;44120:72;44188:2;44177:9;44173:18;44164:6;44120:72;:::i;:::-;43867:332;;;;;:::o;44205:166::-;44345:18;44341:1;44333:6;44329:14;44322:42;44205:166;:::o;44377:366::-;44519:3;44540:67;44604:2;44599:3;44540:67;:::i;:::-;44533:74;;44616:93;44705:3;44616:93;:::i;:::-;44734:2;44729:3;44725:12;44718:19;;44377:366;;;:::o;44749:419::-;44915:4;44953:2;44942:9;44938:18;44930:26;;45002:9;44996:4;44992:20;44988:1;44977:9;44973:17;44966:47;45030:131;45156:4;45030:131;:::i;:::-;45022:139;;44749:419;;;:::o;45174:181::-;45314:33;45310:1;45302:6;45298:14;45291:57;45174:181;:::o;45361:366::-;45503:3;45524:67;45588:2;45583:3;45524:67;:::i;:::-;45517:74;;45600:93;45689:3;45600:93;:::i;:::-;45718:2;45713:3;45709:12;45702:19;;45361:366;;;:::o;45733:419::-;45899:4;45937:2;45926:9;45922:18;45914:26;;45986:9;45980:4;45976:20;45972:1;45961:9;45957:17;45950:47;46014:131;46140:4;46014:131;:::i;:::-;46006:139;;45733:419;;;:::o;46158:140::-;46207:9;46240:52;46258:33;46267:23;46284:5;46267:23;:::i;:::-;46258:33;:::i;:::-;46240:52;:::i;:::-;46227:65;;46158:140;;;:::o;46304:129::-;46390:36;46420:5;46390:36;:::i;:::-;46385:3;46378:49;46304:129;;:::o;46439:330::-;46559:4;46597:2;46586:9;46582:18;46574:26;;46610:70;46677:1;46666:9;46662:17;46653:6;46610:70;:::i;:::-;46690:72;46758:2;46747:9;46743:18;46734:6;46690:72;:::i;:::-;46439:330;;;;;:::o;46775:170::-;46915:22;46911:1;46903:6;46899:14;46892:46;46775:170;:::o;46951:366::-;47093:3;47114:67;47178:2;47173:3;47114:67;:::i;:::-;47107:74;;47190:93;47279:3;47190:93;:::i;:::-;47308:2;47303:3;47299:12;47292:19;;46951:366;;;:::o;47323:419::-;47489:4;47527:2;47516:9;47512:18;47504:26;;47576:9;47570:4;47566:20;47562:1;47551:9;47547:17;47540:47;47604:131;47730:4;47604:131;:::i;:::-;47596:139;;47323:419;;;:::o;47748:553::-;47925:4;47963:3;47952:9;47948:19;47940:27;;47977:71;48045:1;48034:9;48030:17;48021:6;47977:71;:::i;:::-;48058:72;48126:2;48115:9;48111:18;48102:6;48058:72;:::i;:::-;48140;48208:2;48197:9;48193:18;48184:6;48140:72;:::i;:::-;48222;48290:2;48279:9;48275:18;48266:6;48222:72;:::i;:::-;47748:553;;;;;;;:::o;48307:634::-;48528:4;48566:2;48555:9;48551:18;48543:26;;48615:9;48609:4;48605:20;48601:1;48590:9;48586:17;48579:47;48643:108;48746:4;48737:6;48643:108;:::i;:::-;48635:116;;48798:9;48792:4;48788:20;48783:2;48772:9;48768:18;48761:48;48826:108;48929:4;48920:6;48826:108;:::i;:::-;48818:116;;48307:634;;;;;:::o;48947:98::-;48998:6;49032:5;49026:12;49016:22;;48947:98;;;:::o;49051:168::-;49134:11;49168:6;49163:3;49156:19;49208:4;49203:3;49199:14;49184:29;;49051:168;;;;:::o;49225:373::-;49311:3;49339:38;49371:5;49339:38;:::i;:::-;49393:70;49456:6;49451:3;49393:70;:::i;:::-;49386:77;;49472:65;49530:6;49525:3;49518:4;49511:5;49507:16;49472:65;:::i;:::-;49562:29;49584:6;49562:29;:::i;:::-;49557:3;49553:39;49546:46;;49315:283;49225:373;;;;:::o;49604:1053::-;49927:4;49965:3;49954:9;49950:19;49942:27;;49979:71;50047:1;50036:9;50032:17;50023:6;49979:71;:::i;:::-;50060:72;50128:2;50117:9;50113:18;50104:6;50060:72;:::i;:::-;50179:9;50173:4;50169:20;50164:2;50153:9;50149:18;50142:48;50207:108;50310:4;50301:6;50207:108;:::i;:::-;50199:116;;50362:9;50356:4;50352:20;50347:2;50336:9;50332:18;50325:48;50390:108;50493:4;50484:6;50390:108;:::i;:::-;50382:116;;50546:9;50540:4;50536:20;50530:3;50519:9;50515:19;50508:49;50574:76;50645:4;50636:6;50574:76;:::i;:::-;50566:84;;49604:1053;;;;;;;;:::o;50663:141::-;50719:5;50750:6;50744:13;50735:22;;50766:32;50792:5;50766:32;:::i;:::-;50663:141;;;;:::o;50810:349::-;50879:6;50928:2;50916:9;50907:7;50903:23;50899:32;50896:119;;;50934:79;;:::i;:::-;50896:119;51054:1;51079:63;51134:7;51125:6;51114:9;51110:22;51079:63;:::i;:::-;51069:73;;51025:127;50810:349;;;;:::o;51165:751::-;51388:4;51426:3;51415:9;51411:19;51403:27;;51440:71;51508:1;51497:9;51493:17;51484:6;51440:71;:::i;:::-;51521:72;51589:2;51578:9;51574:18;51565:6;51521:72;:::i;:::-;51603;51671:2;51660:9;51656:18;51647:6;51603:72;:::i;:::-;51685;51753:2;51742:9;51738:18;51729:6;51685:72;:::i;:::-;51805:9;51799:4;51795:20;51789:3;51778:9;51774:19;51767:49;51833:76;51904:4;51895:6;51833:76;:::i;:::-;51825:84;;51165:751;;;;;;;;:::o
Swarm Source
ipfs://6bd34faf8a267156e48376a0357dc4c8061bdf2760bf0eaa62c05247701ddd2d
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.