Source Code
Overview
GLMR Balance
GLMR Value
$0.00Latest 11 from a total of 11 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Add Co Owner | 11427734 | 216 days ago | IN | 0 GLMR | 0.003928 | ||||
| Unpause | 11427713 | 216 days ago | IN | 0 GLMR | 0.003891 | ||||
| Set Vice Directo... | 11427709 | 216 days ago | IN | 0 GLMR | 0.003957 | ||||
| Add Co Owner | 11427559 | 216 days ago | IN | 0 GLMR | 0.003928 | ||||
| Mint And Check U... | 11427535 | 216 days ago | IN | 0 GLMR | 0.00390725 | ||||
| Set Vice Directo... | 11427533 | 216 days ago | IN | 0 GLMR | 0.003957 | ||||
| Mint And Check U... | 11427528 | 216 days ago | IN | 0 GLMR | 0.00387825 | ||||
| Add Co Owner | 11427526 | 216 days ago | IN | 0 GLMR | 0.003928 | ||||
| Mint And Check U... | 11427510 | 216 days ago | IN | 0 GLMR | 0.00387825 | ||||
| Add New Nft Type | 11427502 | 216 days ago | IN | 0 GLMR | 0.005307 | ||||
| Add Co Owner | 11427428 | 216 days ago | IN | 0 GLMR | 0.003928 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TOKEN2049
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity)
/**
*Submitted for verification at moonbeam.moonscan.io on 2025-06-23
*/
// File: @openzeppelin/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: @openzeppelin/contracts/token/ERC1155/IERC1155.sol
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.20;
/**
* @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.1.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)
pragma solidity ^0.8.20;
/**
* @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.1.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.20;
/**
* @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.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
// File: @openzeppelin/contracts/token/ERC1155/utils/ERC1155Utils.sol
// OpenZeppelin Contracts (last updated v5.3.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(32, reason), 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(32, reason), mload(reason))
}
}
}
}
}
}
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// File: @openzeppelin/contracts/utils/introspection/ERC165.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
// File: @openzeppelin/contracts/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.3.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 bytes32;
*
* // 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.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}
// File: @openzeppelin/contracts/utils/math/Math.sol
// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
*/
function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
assembly ("memory-safe") {
low := add(a, b)
high := lt(low, a)
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
*/
function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = high * 2²⁵⁶ + low.
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
low := mul(a, b)
high := sub(sub(mm, low), lt(mm, low))
}
}
/**
* @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
success = c >= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a - b;
success = c <= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a * b;
assembly ("memory-safe") {
// Only true when the multiplication doesn't overflow
// (c / a == b) || (a == 0)
success := or(eq(div(c, a), b), iszero(a))
}
// equivalent to: success ? c : 0
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `DIV` opcode returns zero when the denominator is 0.
result := div(a, b)
}
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `MOD` opcode returns zero when the denominator is 0.
result := mod(a, b)
}
}
}
/**
* @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryAdd(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
*/
function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
(, uint256 result) = trySub(a, b);
return result;
}
/**
* @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryMul(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (high == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return low / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= high) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [high low].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
high := sub(high, gt(remainder, low))
low := sub(low, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly ("memory-safe") {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [high low] by twos.
low := div(low, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from high into low.
low |= high * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
// is no longer required.
result = low * inverse;
return result;
}
}
/**
* @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
*/
function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
if (high >= 1 << n) {
Panic.panic(Panic.UNDER_OVERFLOW);
}
return (high << (256 - n)) | (low >> n);
}
}
/**
* @dev Calculates x * y >> n with full precision, following the selected rounding direction.
*/
function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;
// Shifts value right by the current result and use it as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
assembly ("memory-safe") {
r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
}
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}
// File: @openzeppelin/contracts/utils/Arrays.sol
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol)
// This file was procedurally generated from scripts/generate/templates/Arrays.js.
pragma solidity ^0.8.20;
/**
* @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 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 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 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, of 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, of 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, of initialize elements if length is increased.
*/
function unsafeSetLength(uint256[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
}
// File: @openzeppelin/contracts/token/ERC1155/ERC1155.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/ERC1155.sol)
pragma solidity ^0.8.20;
/**
* @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_);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
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;
}
/**
* @dev See {IERC1155-balanceOf}.
*/
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;
}
/**
* @dev See {IERC1155-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC1155-isApprovedForAll}.
*/
function isApprovedForAll(address account, address operator) public view virtual returns (bool) {
return _operatorApprovals[account][operator];
}
/**
* @dev See {IERC1155-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual {
address sender = _msgSender();
if (from != sender && !isApprovedForAll(from, sender)) {
revert ERC1155MissingApprovalForAll(sender, from);
}
_safeTransferFrom(from, to, id, value, data);
}
/**
* @dev See {IERC1155-safeBatchTransferFrom}.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) public virtual {
address sender = _msgSender();
if (from != sender && !isApprovedForAll(from, sender)) {
revert ERC1155MissingApprovalForAll(sender, from);
}
_safeBatchTransferFrom(from, to, ids, values, data);
}
/**
* @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.
*/
function _updateWithAcceptanceCheck(
address from,
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) internal virtual {
_update(from, to, ids, values);
if (to != address(0)) {
address operator = _msgSender();
if (ids.length == 1) {
uint256 id = ids.unsafeMemoryAccess(0);
uint256 value = values.unsafeMemoryAccess(0);
ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data);
} else {
ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, 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);
}
/**
* @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);
}
/**
* @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);
}
/**
* @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);
}
/**
* @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, "");
}
/**
* @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, "");
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the zero address.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
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/IAccessControl.sol
// OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC-165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted to signal this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
* Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}
// File: @openzeppelin/contracts/access/AccessControl.sol
// OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}
// 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/utils/math/SignedMath.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
}
}
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
// Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
// taking advantage of the most significant (or "sign" bit) in two's complement representation.
// This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
// the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
int256 mask = n >> 255;
// A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
return uint256((n + mask) ^ mask);
}
}
}
// File: @openzeppelin/contracts/utils/Strings.sol
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
/**
* @dev String operations.
*/
library Strings {
using SafeCast for *;
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
uint256 private constant SPECIAL_CHARS_LOOKUP =
(1 << 0x08) | // backspace
(1 << 0x09) | // tab
(1 << 0x0a) | // newline
(1 << 0x0c) | // form feed
(1 << 0x0d) | // carriage return
(1 << 0x22) | // double quote
(1 << 0x5c); // backslash
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev The string being parsed contains characters that are not in scope of the given base.
*/
error StringsInvalidChar();
/**
* @dev The string being parsed is not a properly formatted address.
*/
error StringsInvalidAddressFormat();
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly ("memory-safe") {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly ("memory-safe") {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
* representation, according to EIP-55.
*/
function toChecksumHexString(address addr) internal pure returns (string memory) {
bytes memory buffer = bytes(toHexString(addr));
// hash the hex part of buffer (skip length + 2 bytes, length 40)
uint256 hashValue;
assembly ("memory-safe") {
hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
}
for (uint256 i = 41; i > 1; --i) {
// possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
// case shift by xoring with 0x20
buffer[i] ^= 0x20;
}
hashValue >>= 4;
}
return string(buffer);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
/**
* @dev Parse a decimal string and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input) internal pure returns (uint256) {
return parseUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[0-9]*`
* - The result must fit into an `uint256` type
*/
function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
uint256 result = 0;
for (uint256 i = begin; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 9) return (false, 0);
result *= 10;
result += chr;
}
return (true, result);
}
/**
* @dev Parse a decimal string and returns the value as a `int256`.
*
* Requirements:
* - The string must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input) internal pure returns (int256) {
return parseInt(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `[-+]?[0-9]*`
* - The result must fit in an `int256` type.
*/
function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {
(bool success, int256 value) = tryParseInt(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
* the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {
return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
}
uint256 private constant ABS_MIN_INT256 = 2 ** 255;
/**
* @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
* character or if the result does not fit in a `int256`.
*
* NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
*/
function tryParseInt(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, int256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseIntUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseIntUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, int256 value) {
bytes memory buffer = bytes(input);
// Check presence of a negative sign.
bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
bool positiveSign = sign == bytes1("+");
bool negativeSign = sign == bytes1("-");
uint256 offset = (positiveSign || negativeSign).toUint();
(bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);
if (absSuccess && absValue < ABS_MIN_INT256) {
return (true, negativeSign ? -int256(absValue) : int256(absValue));
} else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
return (true, type(int256).min);
} else return (false, 0);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input) internal pure returns (uint256) {
return parseHexUint(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
* - The result must fit in an `uint256` type.
*/
function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
(bool success, uint256 value) = tryParseHexUint(input, begin, end);
if (!success) revert StringsInvalidChar();
return value;
}
/**
* @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {
return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
* invalid character.
*
* NOTE: This function will revert if the result does not fit in a `uint256`.
*/
function tryParseHexUint(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, uint256 value) {
if (end > bytes(input).length || begin > end) return (false, 0);
return _tryParseHexUintUncheckedBounds(input, begin, end);
}
/**
* @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
* `begin <= end <= input.length`. Other inputs would result in undefined behavior.
*/
function _tryParseHexUintUncheckedBounds(
string memory input,
uint256 begin,
uint256 end
) private pure returns (bool success, uint256 value) {
bytes memory buffer = bytes(input);
// skip 0x prefix if present
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 offset = hasPrefix.toUint() * 2;
uint256 result = 0;
for (uint256 i = begin + offset; i < end; ++i) {
uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
if (chr > 15) return (false, 0);
result *= 16;
unchecked {
// Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
// This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.
result += chr;
}
}
return (true, result);
}
/**
* @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
*
* Requirements:
* - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input) internal pure returns (address) {
return parseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and
* `end` (excluded).
*
* Requirements:
* - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
*/
function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {
(bool success, address value) = tryParseAddress(input, begin, end);
if (!success) revert StringsInvalidAddressFormat();
return value;
}
/**
* @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
* formatted address. See {parseAddress-string} requirements.
*/
function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
return tryParseAddress(input, 0, bytes(input).length);
}
/**
* @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
* formatted address. See {parseAddress-string-uint256-uint256} requirements.
*/
function tryParseAddress(
string memory input,
uint256 begin,
uint256 end
) internal pure returns (bool success, address value) {
if (end > bytes(input).length || begin > end) return (false, address(0));
bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
uint256 expectedLength = 40 + hasPrefix.toUint() * 2;
// check that input is the correct length
if (end - begin == expectedLength) {
// length guarantees that this does not overflow, and value is at most type(uint160).max
(bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);
return (s, address(uint160(v)));
} else {
return (false, address(0));
}
}
function _tryParseChr(bytes1 chr) private pure returns (uint8) {
uint8 value = uint8(chr);
// Try to parse `chr`:
// - Case 1: [0-9]
// - Case 2: [a-f]
// - Case 3: [A-F]
// - otherwise not supported
unchecked {
if (value > 47 && value < 58) value -= 48;
else if (value > 96 && value < 103) value -= 87;
else if (value > 64 && value < 71) value -= 55;
else return type(uint8).max;
}
return value;
}
/**
* @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.
*
* WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.
*
* NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of
* RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode
* characters that are not in this range, but other tooling may provide different results.
*/
function escapeJSON(string memory input) internal pure returns (string memory) {
bytes memory buffer = bytes(input);
bytes memory output = new bytes(2 * buffer.length); // worst case scenario
uint256 outputLength = 0;
for (uint256 i; i < buffer.length; ++i) {
bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));
if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {
output[outputLength++] = "\\";
if (char == 0x08) output[outputLength++] = "b";
else if (char == 0x09) output[outputLength++] = "t";
else if (char == 0x0a) output[outputLength++] = "n";
else if (char == 0x0c) output[outputLength++] = "f";
else if (char == 0x0d) output[outputLength++] = "r";
else if (char == 0x5c) output[outputLength++] = "\\";
else if (char == 0x22) {
// solhint-disable-next-line quotes
output[outputLength++] = '"';
}
} else {
output[outputLength++] = char;
}
}
// write the actual length and deallocate unused memory
assembly ("memory-safe") {
mstore(output, outputLength)
mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))
}
return string(output);
}
/**
* @dev Reads a bytes32 from a bytes array without bounds checking.
*
* NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
* assembly block as such would prevent some optimizations.
*/
function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
// This is not memory safe in the general case, but all calls to this private function are within bounds.
assembly ("memory-safe") {
value := mload(add(buffer, add(0x20, offset)))
}
}
}
// File: contracts/token2049.sol
pragma solidity ^0.8.20;
/**
* @notice Contratto TOKEN2049, creato da @SFY_Labs. Gestisce una collezione
* dinamica di NFT con meccaniche soulbound e sblocco configurabile.
* Compatibile con OpenZeppelin v5.0+.
*/
contract TOKEN2049 is ERC1155, AccessControl, Pausable {
// --- Costanti e Ruoli ---
bytes32 public constant CO_OWNER_ROLE = keccak256("CO_OWNER_ROLE");
bytes32 public constant VICE_DIRECTOR_ROLE = keccak256("VICE_DIRECTOR_ROLE");
// --- Stato del Contratto ---
uint256 public totalNftTypes;
uint256 public soulboundUnlockCount;
mapping(uint256 => string) private _tokenURIs;
mapping(address => bool) private _isUnlocked;
// --- Eventi ---
event CollectionUnlocked(address indexed user);
event ViceDirectorSet(address indexed newViceDirector);
event NftTypeAdded(uint256 indexed tokenId, string metadataCID);
event SoulboundUnlockCountChanged(uint256 newCount);
// --- Constructor ---
constructor(address initialOwner) ERC1155("ipfs://") {
require(initialOwner != address(0), "Owner non puo' essere l'indirizzo zero");
_grantRole(DEFAULT_ADMIN_ROLE, initialOwner);
_grantRole(CO_OWNER_ROLE, initialOwner);
soulboundUnlockCount = 2; // Imposta il valore di default per lo sblocco a 2
}
// --- Funzioni di Gestione NFT e Contratto ---
function addNewNftType(string memory metadataCID) public onlyRole(CO_OWNER_ROLE) {
uint256 newTypeId = totalNftTypes;
_tokenURIs[newTypeId] = metadataCID;
totalNftTypes++;
emit NftTypeAdded(newTypeId, metadataCID);
}
function setSoulboundUnlockCount(uint256 newCount) public onlyRole(CO_OWNER_ROLE) {
require(newCount > 0, "Conteggio non puo' essere zero");
soulboundUnlockCount = newCount;
emit SoulboundUnlockCountChanged(newCount);
}
// --- Gestione dei Ruoli ---
function addCoOwner(address coOwner) public onlyRole(DEFAULT_ADMIN_ROLE) { grantRole(CO_OWNER_ROLE, coOwner); }
function removeCoOwner(address coOwner) public onlyRole(DEFAULT_ADMIN_ROLE) { revokeRole(CO_OWNER_ROLE, coOwner); }
function setViceDirector(address viceDirector) public onlyRole(CO_OWNER_ROLE) { grantRole(VICE_DIRECTOR_ROLE, viceDirector); emit ViceDirectorSet(viceDirector); }
function removeViceDirector(address viceDirector) public onlyRole(CO_OWNER_ROLE) { revokeRole(VICE_DIRECTOR_ROLE, viceDirector); }
// --- Funzioni Pausable ---
function pause() public onlyRole(CO_OWNER_ROLE) { _pause(); }
function unpause() public onlyRole(CO_OWNER_ROLE) { _unpause(); }
// --- Logica di Minting e Sblocco ---
function mintAndCheckUnlock(address to, uint256 tokenId) public onlyRole(VICE_DIRECTOR_ROLE) {
require(tokenId < totalNftTypes, "TOKEN2049: Token ID non valido o non ancora creato");
require(to != address(0), "TOKEN2049: Non si puo' mintare all'indirizzo zero");
require(balanceOf(to, tokenId) == 0, "TOKEN2049: NFT gia' posseduto");
_mint(to, tokenId, 1, "");
if (!_isUnlocked[to]) {
bool hasEnough = _checkUnlockCondition(to);
if (hasEnough) {
_unlockCollection(to);
}
}
}
function _unlockCollection(address user) internal {
_isUnlocked[user] = true;
emit CollectionUnlocked(user);
}
function _checkUnlockCondition(address user) internal view returns (bool) {
if (totalNftTypes == 0) return false;
uint256 distinctOwnedCount = 0;
for (uint256 i = 0; i < totalNftTypes; i++) {
if (balanceOf(user, i) > 0) {
distinctOwnedCount++;
}
}
return distinctOwnedCount >= soulboundUnlockCount;
}
// --- Hook Centralizzato per Logica Soulbound e Pausable (Stile OpenZeppelin 5.0+) ---
function _update(address from, address to, uint256[] memory ids, uint256[] memory values)
internal virtual override
{
if (paused()) {
revert("Pausable: contract is paused");
}
if (from != address(0) && to != address(0)) {
require(_isUnlocked[from], "TOKEN2049: Collezione bloccata, NFT non trasferibile.");
}
super._update(from, to, ids, values);
}
// --- Funzioni di Lettura (View) ---
function uri(uint256 tokenId) public view override returns (string memory) {
require(tokenId < totalNftTypes, "TOKEN2049: Token ID non valido o non ancora creato");
return string(abi.encodePacked("ipfs://", _tokenURIs[tokenId]));
}
function isCollectionUnlocked(address user) public view returns (bool) {
return _isUnlocked[user];
}
// --- Funzioni di Supporto OpenZeppelin ---
function supportsInterface(bytes4 interfaceId) public view override(ERC1155, AccessControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"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"},{"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"}],"name":"CollectionUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"metadataCID","type":"string"}],"name":"NftTypeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newCount","type":"uint256"}],"name":"SoulboundUnlockCountChanged","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":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":"address","name":"newViceDirector","type":"address"}],"name":"ViceDirectorSet","type":"event"},{"inputs":[],"name":"CO_OWNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VICE_DIRECTOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"coOwner","type":"address"}],"name":"addCoOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"metadataCID","type":"string"}],"name":"addNewNftType","outputs":[],"stateMutability":"nonpayable","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":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":"user","type":"address"}],"name":"isCollectionUnlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mintAndCheckUnlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"coOwner","type":"address"}],"name":"removeCoOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"viceDirector","type":"address"}],"name":"removeViceDirector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","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":"uint256","name":"newCount","type":"uint256"}],"name":"setSoulboundUnlockCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"viceDirector","type":"address"}],"name":"setViceDirector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"soulboundUnlockCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalNftTypes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801562000010575f80fd5b506040516200407a3803806200407a833981810160405281019062000036919062000340565b6040518060400160405280600781526020017f697066733a2f2f000000000000000000000000000000000000000000000000008152506200007d816200015f60201b60201c565b505f60045f6101000a81548160ff0219169083151502179055505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000108576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000ff90620003f4565b60405180910390fd5b6200011c5f801b826200017460201b60201c565b506200014f7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884826200017460201b60201c565b506002600681905550506200075c565b806002908162000170919062000678565b5050565b5f6200018783836200027060201b60201c565b6200026657600160035f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555062000202620002d460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600190506200026a565b5f90505b92915050565b5f60035f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f33905090565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6200030a82620002df565b9050919050565b6200031c81620002fe565b811462000327575f80fd5b50565b5f815190506200033a8162000311565b92915050565b5f60208284031215620003585762000357620002db565b5b5f62000367848285016200032a565b91505092915050565b5f82825260208201905092915050565b7f4f776e6572206e6f6e2070756f2720657373657265206c27696e646972697a7a5f8201527f6f207a65726f0000000000000000000000000000000000000000000000000000602082015250565b5f620003dc60268362000370565b9150620003e98262000380565b604082019050919050565b5f6020820190508181035f8301526200040d81620003ce565b9050919050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200049057607f821691505b602082108103620004a657620004a56200044b565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026200050a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620004cd565b620005168683620004cd565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620005606200055a62000554846200052e565b62000537565b6200052e565b9050919050565b5f819050919050565b6200057b8362000540565b620005936200058a8262000567565b848454620004d9565b825550505050565b5f90565b620005a96200059b565b620005b681848462000570565b505050565b5b81811015620005dd57620005d15f826200059f565b600181019050620005bc565b5050565b601f8211156200062c57620005f681620004ac565b6200060184620004be565b8101602085101562000611578190505b620006296200062085620004be565b830182620005bb565b50505b505050565b5f82821c905092915050565b5f6200064e5f198460080262000631565b1980831691505092915050565b5f6200066883836200063d565b9150826002028217905092915050565b620006838262000414565b67ffffffffffffffff8111156200069f576200069e6200041e565b5b620006ab825462000478565b620006b8828285620005e1565b5f60209050601f831160018114620006ee575f8415620006d9578287015190505b620006e585826200065b565b86555062000754565b601f198416620006fe86620004ac565b5f5b82811015620007275784890151825560018201915060208501945060208101905062000700565b8683101562000747578489015162000743601f8916826200063d565b8355505b6001600288020188555050505b505050505050565b613910806200076a5f395ff3fe608060405234801561000f575f80fd5b50600436106101cc575f3560e01c80634e1273f411610102578063a217fddf116100a0578063e985e9c51161006f578063e985e9c514610500578063ec475e6314610530578063eee1f2561461054c578063f242432a14610568576101cc565b8063a217fddf1461048c578063a22cb465146104aa578063b0b75d4c146104c6578063d547741f146104e4576101cc565b806369b2ac8e116100dc57806369b2ac8e1461041a5780638456cb591461043657806391d14854146104405780639b4dcaef14610470576101cc565b80634e1273f4146103b0578063563a4024146103e05780635c975abb146103fc576101cc565b80632eb2c2d61161016f57806336568abe1161014957806336568abe1461034e57806336c3ccad1461036a5780633f4ba83a146103885780634071e99614610392576101cc565b80632eb2c2d6146102fa5780632f2ff15d1461031657806330fcc9d814610332576101cc565b80631a57dec7116101ab5780631a57dec7146102605780631ecc16d614610290578063248a9ca3146102ac5780632641a1db146102dc576101cc565b8062fdd58e146101d057806301ffc9a7146102005780630e89341c14610230575b5f80fd5b6101ea60048036038101906101e5919061246f565b610584565b6040516101f791906124bc565b60405180910390f35b61021a6004803603810190610215919061252a565b6105d9565b604051610227919061256f565b60405180910390f35b61024a60048036038101906102459190612588565b6105ea565b604051610257919061263d565b60405180910390f35b61027a6004803603810190610275919061265d565b610667565b604051610287919061256f565b60405180910390f35b6102aa60048036038101906102a5919061265d565b6106b9565b005b6102c660048036038101906102c191906126bb565b610711565b6040516102d391906126f5565b60405180910390f35b6102e461072e565b6040516102f191906126f5565b60405180910390f35b610314600480360381019061030f91906128fe565b610752565b005b610330600480360381019061032b91906129c9565b6107f9565b005b61034c6004803603810190610347919061246f565b61081b565b005b610368600480360381019061036391906129c9565b6109ce565b005b610372610a49565b60405161037f91906126f5565b60405180910390f35b610390610a6d565b005b61039a610aa2565b6040516103a791906124bc565b60405180910390f35b6103ca60048036038101906103c59190612ac7565b610aa8565b6040516103d79190612bf4565b60405180910390f35b6103fa60048036038101906103f5919061265d565b610bb5565b005b610404610bef565b604051610411919061256f565b60405180910390f35b610434600480360381019061042f919061265d565b610c04565b005b61043e610c3e565b005b61045a600480360381019061045591906129c9565b610c73565b604051610467919061256f565b60405180910390f35b61048a6004803603810190610485919061265d565b610cd7565b005b610494610d72565b6040516104a191906126f5565b60405180910390f35b6104c460048036038101906104bf9190612c3e565b610d78565b005b6104ce610d8e565b6040516104db91906124bc565b60405180910390f35b6104fe60048036038101906104f991906129c9565b610d94565b005b61051a60048036038101906105159190612c7c565b610db6565b604051610527919061256f565b60405180910390f35b61054a60048036038101906105459190612588565b610e44565b005b61056660048036038101906105619190612d58565b610ef2565b005b610582600480360381019061057d9190612d9f565b610f95565b005b5f805f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f6105e38261103c565b9050919050565b60606005548210610630576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062790612ea2565b60405180910390fd5b60075f8381526020019081526020015f206040516020016106519190613003565b6040516020818303038152906040529050919050565b5f60085f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e68846106e3816110b5565b61070d7fc58d91fb4dda921afde41e2f2e1ed1f6ccb329b576dadab9c12ea0110691e26983610d94565b5050565b5f60035f8381526020019081526020015f20600101549050919050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e688481565b5f61075b6110c9565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141580156107a0575061079e8682610db6565b155b156107e45780866040517fe237d9220000000000000000000000000000000000000000000000000000000081526004016107db929190613033565b60405180910390fd5b6107f186868686866110d0565b505050505050565b61080282610711565b61080b816110b5565b61081583836111c4565b50505050565b7fc58d91fb4dda921afde41e2f2e1ed1f6ccb329b576dadab9c12ea0110691e269610845816110b5565b6005548210610889576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088090612ea2565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036108f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108ee906130ca565b60405180910390fd5b5f6109028484610584565b14610942576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093990613132565b60405180910390fd5b61095d8383600160405180602001604052805f8152506112ae565b60085f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff166109c9575f6109b584611343565b905080156109c7576109c6846113a5565b5b505b505050565b6109d66110c9565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610a3a576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a448282611440565b505050565b7fc58d91fb4dda921afde41e2f2e1ed1f6ccb329b576dadab9c12ea0110691e26981565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884610a97816110b5565b610a9f61152a565b50565b60055481565b60608151835114610af457815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401610aeb929190613150565b60405180910390fd5b5f835167ffffffffffffffff811115610b1057610b0f612712565b5b604051908082528060200260200182016040528015610b3e5781602001602082028036833780820191505090505b5090505f5b8451811015610baa57610b7a610b62828761158b90919063ffffffff16565b610b75838761159e90919063ffffffff16565b610584565b828281518110610b8d57610b8c613177565b5b60200260200101818152505080610ba3906131d1565b9050610b43565b508091505092915050565b5f801b610bc1816110b5565b610beb7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884836107f9565b5050565b5f60045f9054906101000a900460ff16905090565b5f801b610c10816110b5565b610c3a7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e688483610d94565b5050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884610c68816110b5565b610c706115b1565b50565b5f60035f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884610d01816110b5565b610d2b7fc58d91fb4dda921afde41e2f2e1ed1f6ccb329b576dadab9c12ea0110691e269836107f9565b8173ffffffffffffffffffffffffffffffffffffffff167f0cedbb031d30dc9e57df20f971762f557a0256bf980fb94432b616409c9c3e4f60405160405180910390a25050565b5f801b81565b610d8a610d836110c9565b8383611613565b5050565b60065481565b610d9d82610711565b610da6816110b5565b610db08383611440565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884610e6e816110b5565b5f8211610eb0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea790613262565b60405180910390fd5b816006819055507f02d8e51d9780c88f019d2f47dad5b46d8426c47f61ac914640ed40511ce72d3a82604051610ee691906124bc565b60405180910390a15050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884610f1c816110b5565b5f60055490508260075f8381526020019081526020015f209081610f40919061340b565b5060055f815480929190610f53906131d1565b9190505550807f6e0666373abf13b5234cd556935a8e1108d9b24f4f29f2a48a8dbddfd957ca9a84604051610f88919061263d565b60405180910390a2505050565b5f610f9e6110c9565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015610fe35750610fe18682610db6565b155b156110275780866040517fe237d92200000000000000000000000000000000000000000000000000000000815260040161101e929190613033565b60405180910390fd5b611034868686868661177c565b505050505050565b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806110ae57506110ad82611882565b5b9050919050565b6110c6816110c16110c9565b611963565b50565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611140575f6040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161113791906134da565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036111b0575f6040517f01a835140000000000000000000000000000000000000000000000000000000081526004016111a791906134da565b60405180910390fd5b6111bd85858585856119b4565b5050505050565b5f6111cf8383610c73565b6112a457600160035f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506112416110c9565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600190506112a8565b5f90505b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361131e575f6040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161131591906134da565b60405180910390fd5b5f8061132a8585611a60565b9150915061133b5f878484876119b4565b505050505050565b5f8060055403611355575f90506113a0565b5f805b600554811015611395575f61136d8583610584565b111561138257818061137e906131d1565b9250505b808061138d906131d1565b915050611358565b506006548110159150505b919050565b600160085f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f5755b78a79382d9db124a5ec462a3303de6f7efe42d28a79c417aaa4e23fbfbb60405160405180910390a250565b5f61144b8383610c73565b15611520575f60035f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506114bd6110c9565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611524565b5f90505b92915050565b611532611a90565b5f60045f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6115746110c9565b60405161158191906134da565b60405180910390a1565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b6115b9611ad9565b600160045f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586115fc6110c9565b60405161160991906134da565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611683575f6040517fced3e10000000000000000000000000000000000000000000000000000000000815260040161167a91906134da565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161176f919061256f565b60405180910390a3505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036117ec575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016117e391906134da565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361185c575f6040517f01a8351400000000000000000000000000000000000000000000000000000000815260040161185391906134da565b60405180910390fd5b5f806118688585611a60565b9150915061187987878484876119b4565b50505050505050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061194c57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061195c575061195b82611b23565b5b9050919050565b61196d8282610c73565b6119b05780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016119a79291906134f3565b60405180910390fd5b5050565b6119c085858585611b8c565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614611a59575f6119fc6110c9565b90506001845103611a48575f611a1b5f8661159e90919063ffffffff16565b90505f611a315f8661159e90919063ffffffff16565b9050611a41838989858589611cdd565b5050611a57565b611a56818787878787611e8c565b5b505b5050505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b611a98610bef565b611ad7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ace90613564565b60405180910390fd5b565b611ae1610bef565b15611b21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b18906135cc565b60405180910390fd5b565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b611b94610bef565b15611bd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bcb90613634565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614158015611c3c57505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b15611ccb5760085f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611cca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cc1906136c2565b60405180910390fd5b5b611cd78484848461203b565b50505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115611e84578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401611d3d959493929190613732565b6020604051808303815f875af1925050508015611d7857506040513d601f19601f82011682018060405250810190611d75919061379e565b60015b611df9573d805f8114611da6576040519150601f19603f3d011682016040523d82523d5f602084013e611dab565b606091505b505f815103611df157846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611de891906134da565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611e8257846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611e7991906134da565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115612033578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401611eec9594939291906137c9565b6020604051808303815f875af1925050508015611f2757506040513d601f19601f82011682018060405250810190611f24919061379e565b60015b611fa8573d805f8114611f55576040519150601f19603f3d011682016040523d82523d5f602084013e611f5a565b606091505b505f815103611fa057846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611f9791906134da565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461203157846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161202891906134da565b60405180910390fd5b505b505050505050565b805182511461208557815181516040517f5b05999100000000000000000000000000000000000000000000000000000000815260040161207c929190613150565b60405180910390fd5b5f61208e6110c9565b90505f5b8351811015612290575f6120af828661159e90919063ffffffff16565b90505f6120c5838661159e90919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146121e8575f805f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561219457888183856040517f03dee4c500000000000000000000000000000000000000000000000000000000815260040161218b949392919061382f565b60405180910390fd5b8181035f808581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161461227d57805f808481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546122759190613872565b925050819055505b505080612289906131d1565b9050612092565b50600183510361234b575f6122ae5f8561159e90919063ffffffff16565b90505f6122c45f8561159e90919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62858560405161233c929190613150565b60405180910390a450506123ca565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb86866040516123c19291906138a5565b60405180910390a45b5050505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61240b826123e2565b9050919050565b61241b81612401565b8114612425575f80fd5b50565b5f8135905061243681612412565b92915050565b5f819050919050565b61244e8161243c565b8114612458575f80fd5b50565b5f8135905061246981612445565b92915050565b5f8060408385031215612485576124846123da565b5b5f61249285828601612428565b92505060206124a38582860161245b565b9150509250929050565b6124b68161243c565b82525050565b5f6020820190506124cf5f8301846124ad565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612509816124d5565b8114612513575f80fd5b50565b5f8135905061252481612500565b92915050565b5f6020828403121561253f5761253e6123da565b5b5f61254c84828501612516565b91505092915050565b5f8115159050919050565b61256981612555565b82525050565b5f6020820190506125825f830184612560565b92915050565b5f6020828403121561259d5761259c6123da565b5b5f6125aa8482850161245b565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156125ea5780820151818401526020810190506125cf565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61260f826125b3565b61261981856125bd565b93506126298185602086016125cd565b612632816125f5565b840191505092915050565b5f6020820190508181035f8301526126558184612605565b905092915050565b5f60208284031215612672576126716123da565b5b5f61267f84828501612428565b91505092915050565b5f819050919050565b61269a81612688565b81146126a4575f80fd5b50565b5f813590506126b581612691565b92915050565b5f602082840312156126d0576126cf6123da565b5b5f6126dd848285016126a7565b91505092915050565b6126ef81612688565b82525050565b5f6020820190506127085f8301846126e6565b92915050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612748826125f5565b810181811067ffffffffffffffff8211171561276757612766612712565b5b80604052505050565b5f6127796123d1565b9050612785828261273f565b919050565b5f67ffffffffffffffff8211156127a4576127a3612712565b5b602082029050602081019050919050565b5f80fd5b5f6127cb6127c68461278a565b612770565b905080838252602082019050602084028301858111156127ee576127ed6127b5565b5b835b818110156128175780612803888261245b565b8452602084019350506020810190506127f0565b5050509392505050565b5f82601f8301126128355761283461270e565b5b81356128458482602086016127b9565b91505092915050565b5f80fd5b5f67ffffffffffffffff82111561286c5761286b612712565b5b612875826125f5565b9050602081019050919050565b828183375f83830152505050565b5f6128a261289d84612852565b612770565b9050828152602081018484840111156128be576128bd61284e565b5b6128c9848285612882565b509392505050565b5f82601f8301126128e5576128e461270e565b5b81356128f5848260208601612890565b91505092915050565b5f805f805f60a08688031215612917576129166123da565b5b5f61292488828901612428565b955050602061293588828901612428565b945050604086013567ffffffffffffffff811115612956576129556123de565b5b61296288828901612821565b935050606086013567ffffffffffffffff811115612983576129826123de565b5b61298f88828901612821565b925050608086013567ffffffffffffffff8111156129b0576129af6123de565b5b6129bc888289016128d1565b9150509295509295909350565b5f80604083850312156129df576129de6123da565b5b5f6129ec858286016126a7565b92505060206129fd85828601612428565b9150509250929050565b5f67ffffffffffffffff821115612a2157612a20612712565b5b602082029050602081019050919050565b5f612a44612a3f84612a07565b612770565b90508083825260208201905060208402830185811115612a6757612a666127b5565b5b835b81811015612a905780612a7c8882612428565b845260208401935050602081019050612a69565b5050509392505050565b5f82601f830112612aae57612aad61270e565b5b8135612abe848260208601612a32565b91505092915050565b5f8060408385031215612add57612adc6123da565b5b5f83013567ffffffffffffffff811115612afa57612af96123de565b5b612b0685828601612a9a565b925050602083013567ffffffffffffffff811115612b2757612b266123de565b5b612b3385828601612821565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b612b6f8161243c565b82525050565b5f612b808383612b66565b60208301905092915050565b5f602082019050919050565b5f612ba282612b3d565b612bac8185612b47565b9350612bb783612b57565b805f5b83811015612be7578151612bce8882612b75565b9750612bd983612b8c565b925050600181019050612bba565b5085935050505092915050565b5f6020820190508181035f830152612c0c8184612b98565b905092915050565b612c1d81612555565b8114612c27575f80fd5b50565b5f81359050612c3881612c14565b92915050565b5f8060408385031215612c5457612c536123da565b5b5f612c6185828601612428565b9250506020612c7285828601612c2a565b9150509250929050565b5f8060408385031215612c9257612c916123da565b5b5f612c9f85828601612428565b9250506020612cb085828601612428565b9150509250929050565b5f67ffffffffffffffff821115612cd457612cd3612712565b5b612cdd826125f5565b9050602081019050919050565b5f612cfc612cf784612cba565b612770565b905082815260208101848484011115612d1857612d1761284e565b5b612d23848285612882565b509392505050565b5f82601f830112612d3f57612d3e61270e565b5b8135612d4f848260208601612cea565b91505092915050565b5f60208284031215612d6d57612d6c6123da565b5b5f82013567ffffffffffffffff811115612d8a57612d896123de565b5b612d9684828501612d2b565b91505092915050565b5f805f805f60a08688031215612db857612db76123da565b5b5f612dc588828901612428565b9550506020612dd688828901612428565b9450506040612de78882890161245b565b9350506060612df88882890161245b565b925050608086013567ffffffffffffffff811115612e1957612e186123de565b5b612e25888289016128d1565b9150509295509295909350565b7f544f4b454e323034393a20546f6b656e204944206e6f6e2076616c69646f206f5f8201527f206e6f6e20616e636f72612063726561746f0000000000000000000000000000602082015250565b5f612e8c6032836125bd565b9150612e9782612e32565b604082019050919050565b5f6020820190508181035f830152612eb981612e80565b9050919050565b5f81905092915050565b7f697066733a2f2f000000000000000000000000000000000000000000000000005f82015250565b5f612efe600783612ec0565b9150612f0982612eca565b600782019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612f5857607f821691505b602082108103612f6b57612f6a612f14565b5b50919050565b5f819050815f5260205f209050919050565b5f8154612f8f81612f41565b612f998186612ec0565b9450600182165f8114612fb35760018114612fc857612ffa565b60ff1983168652811515820286019350612ffa565b612fd185612f71565b5f5b83811015612ff257815481890152600182019150602081019050612fd3565b838801955050505b50505092915050565b5f61300d82612ef2565b91506130198284612f83565b915081905092915050565b61302d81612401565b82525050565b5f6040820190506130465f830185613024565b6130536020830184613024565b9392505050565b7f544f4b454e323034393a204e6f6e2073692070756f27206d696e7461726520615f8201527f6c6c27696e646972697a7a6f207a65726f000000000000000000000000000000602082015250565b5f6130b46031836125bd565b91506130bf8261305a565b604082019050919050565b5f6020820190508181035f8301526130e1816130a8565b9050919050565b7f544f4b454e323034393a204e4654206769612720706f7373656475746f0000005f82015250565b5f61311c601d836125bd565b9150613127826130e8565b602082019050919050565b5f6020820190508181035f83015261314981613110565b9050919050565b5f6040820190506131635f8301856124ad565b61317060208301846124ad565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6131db8261243c565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361320d5761320c6131a4565b5b600182019050919050565b7f436f6e74656767696f206e6f6e2070756f2720657373657265207a65726f00005f82015250565b5f61324c601e836125bd565b915061325782613218565b602082019050919050565b5f6020820190508181035f83015261327981613240565b9050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026132ca7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261328f565b6132d4868361328f565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61330f61330a6133058461243c565b6132ec565b61243c565b9050919050565b5f819050919050565b613328836132f5565b61333c61333482613316565b84845461329b565b825550505050565b5f90565b613350613344565b61335b81848461331f565b505050565b5b8181101561337e576133735f82613348565b600181019050613361565b5050565b601f8211156133c35761339481612f71565b61339d84613280565b810160208510156133ac578190505b6133c06133b885613280565b830182613360565b50505b505050565b5f82821c905092915050565b5f6133e35f19846008026133c8565b1980831691505092915050565b5f6133fb83836133d4565b9150826002028217905092915050565b613414826125b3565b67ffffffffffffffff81111561342d5761342c612712565b5b6134378254612f41565b613442828285613382565b5f60209050601f831160018114613473575f8415613461578287015190505b61346b85826133f0565b8655506134d2565b601f19841661348186612f71565b5f5b828110156134a857848901518255600182019150602085019450602081019050613483565b868310156134c557848901516134c1601f8916826133d4565b8355505b6001600288020188555050505b505050505050565b5f6020820190506134ed5f830184613024565b92915050565b5f6040820190506135065f830185613024565b61351360208301846126e6565b9392505050565b7f5061757361626c653a206e6f74207061757365640000000000000000000000005f82015250565b5f61354e6014836125bd565b91506135598261351a565b602082019050919050565b5f6020820190508181035f83015261357b81613542565b9050919050565b7f5061757361626c653a20706175736564000000000000000000000000000000005f82015250565b5f6135b66010836125bd565b91506135c182613582565b602082019050919050565b5f6020820190508181035f8301526135e3816135aa565b9050919050565b7f5061757361626c653a20636f6e747261637420697320706175736564000000005f82015250565b5f61361e601c836125bd565b9150613629826135ea565b602082019050919050565b5f6020820190508181035f83015261364b81613612565b9050919050565b7f544f4b454e323034393a20436f6c6c657a696f6e6520626c6f63636174612c205f8201527f4e4654206e6f6e20747261736665726962696c652e0000000000000000000000602082015250565b5f6136ac6035836125bd565b91506136b782613652565b604082019050919050565b5f6020820190508181035f8301526136d9816136a0565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f613704826136e0565b61370e81856136ea565b935061371e8185602086016125cd565b613727816125f5565b840191505092915050565b5f60a0820190506137455f830188613024565b6137526020830187613024565b61375f60408301866124ad565b61376c60608301856124ad565b818103608083015261377e81846136fa565b90509695505050505050565b5f8151905061379881612500565b92915050565b5f602082840312156137b3576137b26123da565b5b5f6137c08482850161378a565b91505092915050565b5f60a0820190506137dc5f830188613024565b6137e96020830187613024565b81810360408301526137fb8186612b98565b9050818103606083015261380f8185612b98565b9050818103608083015261382381846136fa565b90509695505050505050565b5f6080820190506138425f830187613024565b61384f60208301866124ad565b61385c60408301856124ad565b61386960608301846124ad565b95945050505050565b5f61387c8261243c565b91506138878361243c565b925082820190508082111561389f5761389e6131a4565b5b92915050565b5f6040820190508181035f8301526138bd8185612b98565b905081810360208301526138d18184612b98565b9050939250505056fea264697066735822122065b8cecd23c2275e57badbbb0e21b7accb3212423230a3654240a74bb53448b464736f6c63430008140033000000000000000000000000e150519ae293922cfe6217feba3add4726f5e851
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106101cc575f3560e01c80634e1273f411610102578063a217fddf116100a0578063e985e9c51161006f578063e985e9c514610500578063ec475e6314610530578063eee1f2561461054c578063f242432a14610568576101cc565b8063a217fddf1461048c578063a22cb465146104aa578063b0b75d4c146104c6578063d547741f146104e4576101cc565b806369b2ac8e116100dc57806369b2ac8e1461041a5780638456cb591461043657806391d14854146104405780639b4dcaef14610470576101cc565b80634e1273f4146103b0578063563a4024146103e05780635c975abb146103fc576101cc565b80632eb2c2d61161016f57806336568abe1161014957806336568abe1461034e57806336c3ccad1461036a5780633f4ba83a146103885780634071e99614610392576101cc565b80632eb2c2d6146102fa5780632f2ff15d1461031657806330fcc9d814610332576101cc565b80631a57dec7116101ab5780631a57dec7146102605780631ecc16d614610290578063248a9ca3146102ac5780632641a1db146102dc576101cc565b8062fdd58e146101d057806301ffc9a7146102005780630e89341c14610230575b5f80fd5b6101ea60048036038101906101e5919061246f565b610584565b6040516101f791906124bc565b60405180910390f35b61021a6004803603810190610215919061252a565b6105d9565b604051610227919061256f565b60405180910390f35b61024a60048036038101906102459190612588565b6105ea565b604051610257919061263d565b60405180910390f35b61027a6004803603810190610275919061265d565b610667565b604051610287919061256f565b60405180910390f35b6102aa60048036038101906102a5919061265d565b6106b9565b005b6102c660048036038101906102c191906126bb565b610711565b6040516102d391906126f5565b60405180910390f35b6102e461072e565b6040516102f191906126f5565b60405180910390f35b610314600480360381019061030f91906128fe565b610752565b005b610330600480360381019061032b91906129c9565b6107f9565b005b61034c6004803603810190610347919061246f565b61081b565b005b610368600480360381019061036391906129c9565b6109ce565b005b610372610a49565b60405161037f91906126f5565b60405180910390f35b610390610a6d565b005b61039a610aa2565b6040516103a791906124bc565b60405180910390f35b6103ca60048036038101906103c59190612ac7565b610aa8565b6040516103d79190612bf4565b60405180910390f35b6103fa60048036038101906103f5919061265d565b610bb5565b005b610404610bef565b604051610411919061256f565b60405180910390f35b610434600480360381019061042f919061265d565b610c04565b005b61043e610c3e565b005b61045a600480360381019061045591906129c9565b610c73565b604051610467919061256f565b60405180910390f35b61048a6004803603810190610485919061265d565b610cd7565b005b610494610d72565b6040516104a191906126f5565b60405180910390f35b6104c460048036038101906104bf9190612c3e565b610d78565b005b6104ce610d8e565b6040516104db91906124bc565b60405180910390f35b6104fe60048036038101906104f991906129c9565b610d94565b005b61051a60048036038101906105159190612c7c565b610db6565b604051610527919061256f565b60405180910390f35b61054a60048036038101906105459190612588565b610e44565b005b61056660048036038101906105619190612d58565b610ef2565b005b610582600480360381019061057d9190612d9f565b610f95565b005b5f805f8381526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f6105e38261103c565b9050919050565b60606005548210610630576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062790612ea2565b60405180910390fd5b60075f8381526020019081526020015f206040516020016106519190613003565b6040516020818303038152906040529050919050565b5f60085f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e68846106e3816110b5565b61070d7fc58d91fb4dda921afde41e2f2e1ed1f6ccb329b576dadab9c12ea0110691e26983610d94565b5050565b5f60035f8381526020019081526020015f20600101549050919050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e688481565b5f61075b6110c9565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141580156107a0575061079e8682610db6565b155b156107e45780866040517fe237d9220000000000000000000000000000000000000000000000000000000081526004016107db929190613033565b60405180910390fd5b6107f186868686866110d0565b505050505050565b61080282610711565b61080b816110b5565b61081583836111c4565b50505050565b7fc58d91fb4dda921afde41e2f2e1ed1f6ccb329b576dadab9c12ea0110691e269610845816110b5565b6005548210610889576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088090612ea2565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036108f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108ee906130ca565b60405180910390fd5b5f6109028484610584565b14610942576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093990613132565b60405180910390fd5b61095d8383600160405180602001604052805f8152506112ae565b60085f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff166109c9575f6109b584611343565b905080156109c7576109c6846113a5565b5b505b505050565b6109d66110c9565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610a3a576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a448282611440565b505050565b7fc58d91fb4dda921afde41e2f2e1ed1f6ccb329b576dadab9c12ea0110691e26981565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884610a97816110b5565b610a9f61152a565b50565b60055481565b60608151835114610af457815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401610aeb929190613150565b60405180910390fd5b5f835167ffffffffffffffff811115610b1057610b0f612712565b5b604051908082528060200260200182016040528015610b3e5781602001602082028036833780820191505090505b5090505f5b8451811015610baa57610b7a610b62828761158b90919063ffffffff16565b610b75838761159e90919063ffffffff16565b610584565b828281518110610b8d57610b8c613177565b5b60200260200101818152505080610ba3906131d1565b9050610b43565b508091505092915050565b5f801b610bc1816110b5565b610beb7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884836107f9565b5050565b5f60045f9054906101000a900460ff16905090565b5f801b610c10816110b5565b610c3a7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e688483610d94565b5050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884610c68816110b5565b610c706115b1565b50565b5f60035f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884610d01816110b5565b610d2b7fc58d91fb4dda921afde41e2f2e1ed1f6ccb329b576dadab9c12ea0110691e269836107f9565b8173ffffffffffffffffffffffffffffffffffffffff167f0cedbb031d30dc9e57df20f971762f557a0256bf980fb94432b616409c9c3e4f60405160405180910390a25050565b5f801b81565b610d8a610d836110c9565b8383611613565b5050565b60065481565b610d9d82610711565b610da6816110b5565b610db08383611440565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884610e6e816110b5565b5f8211610eb0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea790613262565b60405180910390fd5b816006819055507f02d8e51d9780c88f019d2f47dad5b46d8426c47f61ac914640ed40511ce72d3a82604051610ee691906124bc565b60405180910390a15050565b7f1997ee9f2f22139cc89fe89805cc1964b95c30552dffed30677ad233de4e6884610f1c816110b5565b5f60055490508260075f8381526020019081526020015f209081610f40919061340b565b5060055f815480929190610f53906131d1565b9190505550807f6e0666373abf13b5234cd556935a8e1108d9b24f4f29f2a48a8dbddfd957ca9a84604051610f88919061263d565b60405180910390a2505050565b5f610f9e6110c9565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015610fe35750610fe18682610db6565b155b156110275780866040517fe237d92200000000000000000000000000000000000000000000000000000000815260040161101e929190613033565b60405180910390fd5b611034868686868661177c565b505050505050565b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806110ae57506110ad82611882565b5b9050919050565b6110c6816110c16110c9565b611963565b50565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611140575f6040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161113791906134da565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036111b0575f6040517f01a835140000000000000000000000000000000000000000000000000000000081526004016111a791906134da565b60405180910390fd5b6111bd85858585856119b4565b5050505050565b5f6111cf8383610c73565b6112a457600160035f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506112416110c9565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600190506112a8565b5f90505b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361131e575f6040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161131591906134da565b60405180910390fd5b5f8061132a8585611a60565b9150915061133b5f878484876119b4565b505050505050565b5f8060055403611355575f90506113a0565b5f805b600554811015611395575f61136d8583610584565b111561138257818061137e906131d1565b9250505b808061138d906131d1565b915050611358565b506006548110159150505b919050565b600160085f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f5755b78a79382d9db124a5ec462a3303de6f7efe42d28a79c417aaa4e23fbfbb60405160405180910390a250565b5f61144b8383610c73565b15611520575f60035f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506114bd6110c9565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611524565b5f90505b92915050565b611532611a90565b5f60045f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6115746110c9565b60405161158191906134da565b60405180910390a1565b5f60208202602084010151905092915050565b5f60208202602084010151905092915050565b6115b9611ad9565b600160045f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586115fc6110c9565b60405161160991906134da565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611683575f6040517fced3e10000000000000000000000000000000000000000000000000000000000815260040161167a91906134da565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161176f919061256f565b60405180910390a3505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036117ec575f6040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016117e391906134da565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361185c575f6040517f01a8351400000000000000000000000000000000000000000000000000000000815260040161185391906134da565b60405180910390fd5b5f806118688585611a60565b9150915061187987878484876119b4565b50505050505050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061194c57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061195c575061195b82611b23565b5b9050919050565b61196d8282610c73565b6119b05780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016119a79291906134f3565b60405180910390fd5b5050565b6119c085858585611b8c565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614611a59575f6119fc6110c9565b90506001845103611a48575f611a1b5f8661159e90919063ffffffff16565b90505f611a315f8661159e90919063ffffffff16565b9050611a41838989858589611cdd565b5050611a57565b611a56818787878787611e8c565b5b505b5050505050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b611a98610bef565b611ad7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ace90613564565b60405180910390fd5b565b611ae1610bef565b15611b21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b18906135cc565b60405180910390fd5b565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b611b94610bef565b15611bd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bcb90613634565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614158015611c3c57505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b15611ccb5760085f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611cca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cc1906136c2565b60405180910390fd5b5b611cd78484848461203b565b50505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115611e84578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401611d3d959493929190613732565b6020604051808303815f875af1925050508015611d7857506040513d601f19601f82011682018060405250810190611d75919061379e565b60015b611df9573d805f8114611da6576040519150601f19603f3d011682016040523d82523d5f602084013e611dab565b606091505b505f815103611df157846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611de891906134da565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611e8257846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611e7991906134da565b60405180910390fd5b505b505050505050565b5f8473ffffffffffffffffffffffffffffffffffffffff163b1115612033578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b8152600401611eec9594939291906137c9565b6020604051808303815f875af1925050508015611f2757506040513d601f19601f82011682018060405250810190611f24919061379e565b60015b611fa8573d805f8114611f55576040519150601f19603f3d011682016040523d82523d5f602084013e611f5a565b606091505b505f815103611fa057846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611f9791906134da565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461203157846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161202891906134da565b60405180910390fd5b505b505050505050565b805182511461208557815181516040517f5b05999100000000000000000000000000000000000000000000000000000000815260040161207c929190613150565b60405180910390fd5b5f61208e6110c9565b90505f5b8351811015612290575f6120af828661159e90919063ffffffff16565b90505f6120c5838661159e90919063ffffffff16565b90505f73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146121e8575f805f8481526020019081526020015f205f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561219457888183856040517f03dee4c500000000000000000000000000000000000000000000000000000000815260040161218b949392919061382f565b60405180910390fd5b8181035f808581526020019081526020015f205f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161461227d57805f808481526020019081526020015f205f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546122759190613872565b925050819055505b505080612289906131d1565b9050612092565b50600183510361234b575f6122ae5f8561159e90919063ffffffff16565b90505f6122c45f8561159e90919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62858560405161233c929190613150565b60405180910390a450506123ca565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb86866040516123c19291906138a5565b60405180910390a45b5050505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61240b826123e2565b9050919050565b61241b81612401565b8114612425575f80fd5b50565b5f8135905061243681612412565b92915050565b5f819050919050565b61244e8161243c565b8114612458575f80fd5b50565b5f8135905061246981612445565b92915050565b5f8060408385031215612485576124846123da565b5b5f61249285828601612428565b92505060206124a38582860161245b565b9150509250929050565b6124b68161243c565b82525050565b5f6020820190506124cf5f8301846124ad565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612509816124d5565b8114612513575f80fd5b50565b5f8135905061252481612500565b92915050565b5f6020828403121561253f5761253e6123da565b5b5f61254c84828501612516565b91505092915050565b5f8115159050919050565b61256981612555565b82525050565b5f6020820190506125825f830184612560565b92915050565b5f6020828403121561259d5761259c6123da565b5b5f6125aa8482850161245b565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156125ea5780820151818401526020810190506125cf565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61260f826125b3565b61261981856125bd565b93506126298185602086016125cd565b612632816125f5565b840191505092915050565b5f6020820190508181035f8301526126558184612605565b905092915050565b5f60208284031215612672576126716123da565b5b5f61267f84828501612428565b91505092915050565b5f819050919050565b61269a81612688565b81146126a4575f80fd5b50565b5f813590506126b581612691565b92915050565b5f602082840312156126d0576126cf6123da565b5b5f6126dd848285016126a7565b91505092915050565b6126ef81612688565b82525050565b5f6020820190506127085f8301846126e6565b92915050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612748826125f5565b810181811067ffffffffffffffff8211171561276757612766612712565b5b80604052505050565b5f6127796123d1565b9050612785828261273f565b919050565b5f67ffffffffffffffff8211156127a4576127a3612712565b5b602082029050602081019050919050565b5f80fd5b5f6127cb6127c68461278a565b612770565b905080838252602082019050602084028301858111156127ee576127ed6127b5565b5b835b818110156128175780612803888261245b565b8452602084019350506020810190506127f0565b5050509392505050565b5f82601f8301126128355761283461270e565b5b81356128458482602086016127b9565b91505092915050565b5f80fd5b5f67ffffffffffffffff82111561286c5761286b612712565b5b612875826125f5565b9050602081019050919050565b828183375f83830152505050565b5f6128a261289d84612852565b612770565b9050828152602081018484840111156128be576128bd61284e565b5b6128c9848285612882565b509392505050565b5f82601f8301126128e5576128e461270e565b5b81356128f5848260208601612890565b91505092915050565b5f805f805f60a08688031215612917576129166123da565b5b5f61292488828901612428565b955050602061293588828901612428565b945050604086013567ffffffffffffffff811115612956576129556123de565b5b61296288828901612821565b935050606086013567ffffffffffffffff811115612983576129826123de565b5b61298f88828901612821565b925050608086013567ffffffffffffffff8111156129b0576129af6123de565b5b6129bc888289016128d1565b9150509295509295909350565b5f80604083850312156129df576129de6123da565b5b5f6129ec858286016126a7565b92505060206129fd85828601612428565b9150509250929050565b5f67ffffffffffffffff821115612a2157612a20612712565b5b602082029050602081019050919050565b5f612a44612a3f84612a07565b612770565b90508083825260208201905060208402830185811115612a6757612a666127b5565b5b835b81811015612a905780612a7c8882612428565b845260208401935050602081019050612a69565b5050509392505050565b5f82601f830112612aae57612aad61270e565b5b8135612abe848260208601612a32565b91505092915050565b5f8060408385031215612add57612adc6123da565b5b5f83013567ffffffffffffffff811115612afa57612af96123de565b5b612b0685828601612a9a565b925050602083013567ffffffffffffffff811115612b2757612b266123de565b5b612b3385828601612821565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b612b6f8161243c565b82525050565b5f612b808383612b66565b60208301905092915050565b5f602082019050919050565b5f612ba282612b3d565b612bac8185612b47565b9350612bb783612b57565b805f5b83811015612be7578151612bce8882612b75565b9750612bd983612b8c565b925050600181019050612bba565b5085935050505092915050565b5f6020820190508181035f830152612c0c8184612b98565b905092915050565b612c1d81612555565b8114612c27575f80fd5b50565b5f81359050612c3881612c14565b92915050565b5f8060408385031215612c5457612c536123da565b5b5f612c6185828601612428565b9250506020612c7285828601612c2a565b9150509250929050565b5f8060408385031215612c9257612c916123da565b5b5f612c9f85828601612428565b9250506020612cb085828601612428565b9150509250929050565b5f67ffffffffffffffff821115612cd457612cd3612712565b5b612cdd826125f5565b9050602081019050919050565b5f612cfc612cf784612cba565b612770565b905082815260208101848484011115612d1857612d1761284e565b5b612d23848285612882565b509392505050565b5f82601f830112612d3f57612d3e61270e565b5b8135612d4f848260208601612cea565b91505092915050565b5f60208284031215612d6d57612d6c6123da565b5b5f82013567ffffffffffffffff811115612d8a57612d896123de565b5b612d9684828501612d2b565b91505092915050565b5f805f805f60a08688031215612db857612db76123da565b5b5f612dc588828901612428565b9550506020612dd688828901612428565b9450506040612de78882890161245b565b9350506060612df88882890161245b565b925050608086013567ffffffffffffffff811115612e1957612e186123de565b5b612e25888289016128d1565b9150509295509295909350565b7f544f4b454e323034393a20546f6b656e204944206e6f6e2076616c69646f206f5f8201527f206e6f6e20616e636f72612063726561746f0000000000000000000000000000602082015250565b5f612e8c6032836125bd565b9150612e9782612e32565b604082019050919050565b5f6020820190508181035f830152612eb981612e80565b9050919050565b5f81905092915050565b7f697066733a2f2f000000000000000000000000000000000000000000000000005f82015250565b5f612efe600783612ec0565b9150612f0982612eca565b600782019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612f5857607f821691505b602082108103612f6b57612f6a612f14565b5b50919050565b5f819050815f5260205f209050919050565b5f8154612f8f81612f41565b612f998186612ec0565b9450600182165f8114612fb35760018114612fc857612ffa565b60ff1983168652811515820286019350612ffa565b612fd185612f71565b5f5b83811015612ff257815481890152600182019150602081019050612fd3565b838801955050505b50505092915050565b5f61300d82612ef2565b91506130198284612f83565b915081905092915050565b61302d81612401565b82525050565b5f6040820190506130465f830185613024565b6130536020830184613024565b9392505050565b7f544f4b454e323034393a204e6f6e2073692070756f27206d696e7461726520615f8201527f6c6c27696e646972697a7a6f207a65726f000000000000000000000000000000602082015250565b5f6130b46031836125bd565b91506130bf8261305a565b604082019050919050565b5f6020820190508181035f8301526130e1816130a8565b9050919050565b7f544f4b454e323034393a204e4654206769612720706f7373656475746f0000005f82015250565b5f61311c601d836125bd565b9150613127826130e8565b602082019050919050565b5f6020820190508181035f83015261314981613110565b9050919050565b5f6040820190506131635f8301856124ad565b61317060208301846124ad565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6131db8261243c565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361320d5761320c6131a4565b5b600182019050919050565b7f436f6e74656767696f206e6f6e2070756f2720657373657265207a65726f00005f82015250565b5f61324c601e836125bd565b915061325782613218565b602082019050919050565b5f6020820190508181035f83015261327981613240565b9050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026132ca7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261328f565b6132d4868361328f565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61330f61330a6133058461243c565b6132ec565b61243c565b9050919050565b5f819050919050565b613328836132f5565b61333c61333482613316565b84845461329b565b825550505050565b5f90565b613350613344565b61335b81848461331f565b505050565b5b8181101561337e576133735f82613348565b600181019050613361565b5050565b601f8211156133c35761339481612f71565b61339d84613280565b810160208510156133ac578190505b6133c06133b885613280565b830182613360565b50505b505050565b5f82821c905092915050565b5f6133e35f19846008026133c8565b1980831691505092915050565b5f6133fb83836133d4565b9150826002028217905092915050565b613414826125b3565b67ffffffffffffffff81111561342d5761342c612712565b5b6134378254612f41565b613442828285613382565b5f60209050601f831160018114613473575f8415613461578287015190505b61346b85826133f0565b8655506134d2565b601f19841661348186612f71565b5f5b828110156134a857848901518255600182019150602085019450602081019050613483565b868310156134c557848901516134c1601f8916826133d4565b8355505b6001600288020188555050505b505050505050565b5f6020820190506134ed5f830184613024565b92915050565b5f6040820190506135065f830185613024565b61351360208301846126e6565b9392505050565b7f5061757361626c653a206e6f74207061757365640000000000000000000000005f82015250565b5f61354e6014836125bd565b91506135598261351a565b602082019050919050565b5f6020820190508181035f83015261357b81613542565b9050919050565b7f5061757361626c653a20706175736564000000000000000000000000000000005f82015250565b5f6135b66010836125bd565b91506135c182613582565b602082019050919050565b5f6020820190508181035f8301526135e3816135aa565b9050919050565b7f5061757361626c653a20636f6e747261637420697320706175736564000000005f82015250565b5f61361e601c836125bd565b9150613629826135ea565b602082019050919050565b5f6020820190508181035f83015261364b81613612565b9050919050565b7f544f4b454e323034393a20436f6c6c657a696f6e6520626c6f63636174612c205f8201527f4e4654206e6f6e20747261736665726962696c652e0000000000000000000000602082015250565b5f6136ac6035836125bd565b91506136b782613652565b604082019050919050565b5f6020820190508181035f8301526136d9816136a0565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f613704826136e0565b61370e81856136ea565b935061371e8185602086016125cd565b613727816125f5565b840191505092915050565b5f60a0820190506137455f830188613024565b6137526020830187613024565b61375f60408301866124ad565b61376c60608301856124ad565b818103608083015261377e81846136fa565b90509695505050505050565b5f8151905061379881612500565b92915050565b5f602082840312156137b3576137b26123da565b5b5f6137c08482850161378a565b91505092915050565b5f60a0820190506137dc5f830188613024565b6137e96020830187613024565b81810360408301526137fb8186612b98565b9050818103606083015261380f8185612b98565b9050818103608083015261382381846136fa565b90509695505050505050565b5f6080820190506138425f830187613024565b61384f60208301866124ad565b61385c60408301856124ad565b61386960608301846124ad565b95945050505050565b5f61387c8261243c565b91506138878361243c565b925082820190508082111561389f5761389e6131a4565b5b92915050565b5f6040820190508181035f8301526138bd8185612b98565b905081810360208301526138d18184612b98565b9050939250505056fea264697066735822122065b8cecd23c2275e57badbbb0e21b7accb3212423230a3654240a74bb53448b464736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e150519ae293922cfe6217feba3add4726f5e851
-----Decoded View---------------
Arg [0] : initialOwner (address): 0xe150519ae293922cfE6217FEba3AdD4726f5E851
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000e150519ae293922cfe6217feba3add4726f5e851
Deployed Bytecode Sourcemap
171853:4883:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123354:134;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;176564:169;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;176122:254;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;176388:114;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173999:130;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;143244:122;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;171954:66;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;125177:441;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;143676:138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;174359:601;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;144813:251;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;172027:76;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;174238:65;;;:::i;:::-;;172148:28;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123654:567;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173593:111;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;148265:86;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173710:115;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;174171:61;;;:::i;:::-;;142260:138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173831:162;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;141572:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124294:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;172183:35;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;144107:140;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124512:159;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173299:251;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;173030:257;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;124743:357;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;123354:134;123431:7;123458:9;:13;123468:2;123458:13;;;;;;;;;;;:22;123472:7;123458:22;;;;;;;;;;;;;;;;123451:29;;123354:134;;;;:::o;176564:169::-;176665:4;176689:36;176713:11;176689:23;:36::i;:::-;176682:43;;176564:169;;;:::o;176122:254::-;176182:13;176226;;176216:7;:23;176208:86;;;;;;;;;;;;:::i;:::-;;;;;;;;;176347:10;:19;176358:7;176347:19;;;;;;;;;;;176319:48;;;;;;;;:::i;:::-;;;;;;;;;;;;;176305:63;;176122:254;;;:::o;176388:114::-;176453:4;176477:11;:17;176489:4;176477:17;;;;;;;;;;;;;;;;;;;;;;;;;176470:24;;176388:114;;;:::o;173999:130::-;171994:26;141856:16;141867:4;141856:10;:16::i;:::-;174082:44:::1;172072:31;174113:12;174082:10;:44::i;:::-;173999:130:::0;;:::o;143244:122::-;143309:7;143336:6;:12;143343:4;143336:12;;;;;;;;;;;:22;;;143329:29;;143244:122;;;:::o;171954:66::-;171994:26;171954:66;:::o;125177:441::-;125378:14;125395:12;:10;:12::i;:::-;125378:29;;125430:6;125422:14;;:4;:14;;;;:49;;;;;125441:30;125458:4;125464:6;125441:16;:30::i;:::-;125440:31;125422:49;125418:131;;;125524:6;125532:4;125495:42;;;;;;;;;;;;:::i;:::-;;;;;;;;125418:131;125559:51;125582:4;125588:2;125592:3;125597:6;125605:4;125559:22;:51::i;:::-;125367:251;125177:441;;;;;:::o;143676:138::-;143750:18;143763:4;143750:12;:18::i;:::-;141856:16;141867:4;141856:10;:16::i;:::-;143781:25:::1;143792:4;143798:7;143781:10;:25::i;:::-;;143676:138:::0;;;:::o;174359:601::-;172072:31;141856:16;141867:4;141856:10;:16::i;:::-;174481:13:::1;;174471:7;:23;174463:86;;;;;;;;;;;;:::i;:::-;;;;;;;;;174582:1;174568:16;;:2;:16;;::::0;174560:78:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;174683:1;174657:22;174667:2;174671:7;174657:9;:22::i;:::-;:27;174649:69;;;;;;;;;;;;:::i;:::-;;;;;;;;;174739:25;174745:2;174749:7;174758:1;174739:25;;;;;;;;;;;::::0;:5:::1;:25::i;:::-;174782:11;:15;174794:2;174782:15;;;;;;;;;;;;;;;;;;;;;;;;;174777:176;;174814:14;174831:25;174853:2;174831:21;:25::i;:::-;174814:42;;174875:9;174871:71;;;174905:21;174923:2;174905:17;:21::i;:::-;174871:71;174799:154;174777:176;174359:601:::0;;;:::o;144813:251::-;144929:12;:10;:12::i;:::-;144907:34;;:18;:34;;;144903:104;;144965:30;;;;;;;;;;;;;;144903:104;145019:37;145031:4;145037:18;145019:11;:37::i;:::-;;144813:251;;:::o;172027:76::-;172072:31;172027:76;:::o;174238:65::-;171994:26;141856:16;141867:4;141856:10;:16::i;:::-;174290:10:::1;:8;:10::i;:::-;174238:65:::0;:::o;172148:28::-;;;;:::o;123654:567::-;123781:16;123833:3;:10;123814:8;:15;:29;123810:123;;123893:3;:10;123905:8;:15;123867:54;;;;;;;;;;;;:::i;:::-;;;;;;;;123810:123;123945:30;123992:8;:15;123978:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;123945:63;;124026:9;124021:160;124045:8;:15;124041:1;:19;124021:160;;;124101:68;124111:30;124139:1;124111:8;:27;;:30;;;;:::i;:::-;124143:25;124166:1;124143:3;:22;;:25;;;;:::i;:::-;124101:9;:68::i;:::-;124082:13;124096:1;124082:16;;;;;;;;:::i;:::-;;;;;;;:87;;;;;124062:3;;;;:::i;:::-;;;124021:160;;;;124200:13;124193:20;;;123654:567;;;;:::o;173593:111::-;141617:4;173646:18;;141856:16;141867:4;141856:10;:16::i;:::-;173668:33:::1;171994:26;173693:7;173668:9;:33::i;:::-;173593:111:::0;;:::o;148265:86::-;148312:4;148336:7;;;;;;;;;;;148329:14;;148265:86;:::o;173710:115::-;141617:4;173766:18;;141856:16;141867:4;141856:10;:16::i;:::-;173788:34:::1;171994:26;173814:7;173788:10;:34::i;:::-;173710:115:::0;;:::o;174171:61::-;171994:26;141856:16;141867:4;141856:10;:16::i;:::-;174221:8:::1;:6;:8::i;:::-;174171:61:::0;:::o;142260:138::-;142337:4;142361:6;:12;142368:4;142361:12;;;;;;;;;;;:20;;:29;142382:7;142361:29;;;;;;;;;;;;;;;;;;;;;;;;;142354:36;;142260:138;;;;:::o;173831:162::-;171994:26;141856:16;141867:4;141856:10;:16::i;:::-;173911:43:::1;172072:31;173941:12;173911:9;:43::i;:::-;173977:12;173961:29;;;;;;;;;;;;173831:162:::0;;:::o;141572:49::-;141617:4;141572:49;;;:::o;124294:146::-;124380:52;124399:12;:10;:12::i;:::-;124413:8;124423;124380:18;:52::i;:::-;124294:146;;:::o;172183:35::-;;;;:::o;144107:140::-;144182:18;144195:4;144182:12;:18::i;:::-;141856:16;141867:4;141856:10;:16::i;:::-;144213:26:::1;144225:4;144231:7;144213:11;:26::i;:::-;;144107:140:::0;;;:::o;124512:159::-;124602:4;124626:18;:27;124645:7;124626:27;;;;;;;;;;;;;;;:37;124654:8;124626:37;;;;;;;;;;;;;;;;;;;;;;;;;124619:44;;124512:159;;;;:::o;173299:251::-;171994:26;141856:16;141867:4;141856:10;:16::i;:::-;173411:1:::1;173400:8;:12;173392:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;173481:8;173458:20;:31;;;;173505:37;173533:8;173505:37;;;;;;:::i;:::-;;;;;;;;173299:251:::0;;:::o;173030:257::-;171994:26;141856:16;141867:4;141856:10;:16::i;:::-;173122:17:::1;173142:13;;173122:33;;173190:11;173166:10;:21;173177:9;173166:21;;;;;;;;;;;:35;;;;;;:::i;:::-;;173212:13;;:15;;;;;;;;;:::i;:::-;;;;;;173256:9;173243:36;173267:11;173243:36;;;;;;:::i;:::-;;;;;;;;173111:176;173030:257:::0;;:::o;124743:357::-;124867:14;124884:12;:10;:12::i;:::-;124867:29;;124919:6;124911:14;;:4;:14;;;;:49;;;;;124930:30;124947:4;124953:6;124930:16;:30::i;:::-;124929:31;124911:49;124907:131;;;125013:6;125021:4;124984:42;;;;;;;;;;;;:::i;:::-;;;;;;;;124907:131;125048:44;125066:4;125072:2;125076;125080:5;125087:4;125048:17;:44::i;:::-;124856:244;124743:357;;;;;:::o;141964:204::-;142049:4;142088:32;142073:47;;;:11;:47;;;;:87;;;;142124:36;142148:11;142124:23;:36::i;:::-;142073:87;142066:94;;141964:204;;;:::o;142613:105::-;142680:30;142691:4;142697:12;:10;:12::i;:::-;142680:10;:30::i;:::-;142613:105;:::o;20107:98::-;20160:7;20187:10;20180:17;;20107:98;:::o;130315:459::-;130529:1;130515:16;;:2;:16;;;130511:90;;130586:1;130555:34;;;;;;;;;;;:::i;:::-;;;;;;;;130511:90;130631:1;130615:18;;:4;:18;;;130611:90;;130686:1;130657:32;;;;;;;;;;;:::i;:::-;;;;;;;;130611:90;130711:55;130738:4;130744:2;130748:3;130753:6;130761:4;130711:26;:55::i;:::-;130315:459;;;;;:::o;145690:324::-;145767:4;145789:22;145797:4;145803:7;145789;:22::i;:::-;145784:223;;145860:4;145828:6;:12;145835:4;145828:12;;;;;;;;;;;:20;;:29;145849:7;145828:29;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;145911:12;:10;:12::i;:::-;145884:40;;145902:7;145884:40;;145896:4;145884:40;;;;;;;;;;145946:4;145939:11;;;;145784:223;145990:5;145983:12;;145690:324;;;;;:::o;132096:352::-;132207:1;132193:16;;:2;:16;;;132189:90;;132264:1;132233:34;;;;;;;;;;;:::i;:::-;;;;;;;;132189:90;132290:20;132312:23;132339:29;132358:2;132362:5;132339:18;:29::i;:::-;132289:79;;;;132379:61;132414:1;132418:2;132422:3;132427:6;132435:4;132379:26;:61::i;:::-;132178:270;;132096:352;;;;:::o;175109:405::-;175177:4;175215:1;175198:13;;:18;175194:36;;175225:5;175218:12;;;;175194:36;175243:26;175289:9;175284:153;175308:13;;175304:1;:17;175284:153;;;175368:1;175347:18;175357:4;175363:1;175347:9;:18::i;:::-;:22;175343:83;;;175390:20;;;;;:::i;:::-;;;;175343:83;175323:3;;;;;:::i;:::-;;;;175284:153;;;;175486:20;;175464:18;:42;;175457:49;;;175109:405;;;;:::o;174968:133::-;175049:4;175029:11;:17;175041:4;175029:17;;;;;;;;;;;;;;;;:24;;;;;;;;;;;;;;;;;;175088:4;175069:24;;;;;;;;;;;;174968:133;:::o;146260:325::-;146338:4;146359:22;146367:4;146373:7;146359;:22::i;:::-;146355:223;;;146430:5;146398:6;:12;146405:4;146398:12;;;;;;;;;;;:20;;:29;146419:7;146398:29;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;146482:12;:10;:12::i;:::-;146455:40;;146473:7;146455:40;;146467:4;146455:40;;;;;;;;;;146517:4;146510:11;;;;146355:223;146561:5;146554:12;;146260:325;;;;;:::o;149120:120::-;148129:16;:14;:16::i;:::-;149189:5:::1;149179:7;;:15;;;;;;;;;;;;;;;;;;149210:22;149219:12;:10;:12::i;:::-;149210:22;;;;;;:::i;:::-;;;;;;;;149120:120::o:0;119141:201::-;119227:11;119317:4;119312:3;119308:14;119301:4;119296:3;119292:14;119288:35;119282:42;119275:49;;119141:201;;;;:::o;119961:::-;120047:11;120137:4;120132:3;120128:14;120121:4;120116:3;120112:14;120108:35;120102:42;120095:49;;119961:201;;;;:::o;148861:118::-;147870:19;:17;:19::i;:::-;148931:4:::1;148921:7;;:14;;;;;;;;;;;;;;;;;;148951:20;148958:12;:10;:12::i;:::-;148951:20;;;;;;:::i;:::-;;;;;;;;148861:118::o:0;134690:321::-;134818:1;134798:22;;:8;:22;;;134794:96;;134875:1;134844:34;;;;;;;;;;;:::i;:::-;;;;;;;;134794:96;134938:8;134900:18;:25;134919:5;134900:25;;;;;;;;;;;;;;;:35;134926:8;134900:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;134984:8;134962:41;;134977:5;134962:41;;;134994:8;134962:41;;;;;;:::i;:::-;;;;;;;;134690:321;;;:::o;129429:472::-;129566:1;129552:16;;:2;:16;;;129548:90;;129623:1;129592:34;;;;;;;;;;;:::i;:::-;;;;;;;;129548:90;129668:1;129652:18;;:4;:18;;;129648:90;;129723:1;129694:32;;;;;;;;;;;:::i;:::-;;;;;;;;129648:90;129749:20;129771:23;129798:29;129817:2;129821:5;129798:18;:29::i;:::-;129748:79;;;;129838:55;129865:4;129871:2;129875:3;129880:6;129888:4;129838:26;:55::i;:::-;129537:364;;129429:472;;;;;:::o;122463:310::-;122565:4;122617:26;122602:41;;;:11;:41;;;;:110;;;;122675:37;122660:52;;;:11;:52;;;;122602:110;:163;;;;122729:36;122753:11;122729:23;:36::i;:::-;122602:163;122582:183;;122463:310;;;:::o;142854:201::-;142943:22;142951:4;142957:7;142943;:22::i;:::-;142938:110;;143022:7;143031:4;142989:47;;;;;;;;;;;;:::i;:::-;;;;;;;;142938:110;142854:201;;:::o;128240:718::-;128448:30;128456:4;128462:2;128466:3;128471:6;128448:7;:30::i;:::-;128507:1;128493:16;;:2;:16;;;128489:462;;128526:16;128545:12;:10;:12::i;:::-;128526:31;;128590:1;128576:3;:10;:15;128572:368;;128612:10;128625:25;128648:1;128625:3;:22;;:25;;;;:::i;:::-;128612:38;;128669:13;128685:28;128711:1;128685:6;:25;;:28;;;;:::i;:::-;128669:44;;128732:72;128768:8;128778:4;128784:2;128788;128792:5;128799:4;128732:35;:72::i;:::-;128593:227;;128572:368;;;128845:79;128886:8;128896:4;128902:2;128906:3;128911:6;128919:4;128845:40;:79::i;:::-;128572:368;128511:440;128489:462;128240:718;;;;;:::o;135132:842::-;135243:23;135268;135405:4;135399:11;135389:21;;135477:1;135469:6;135462:17;135617:8;135610:4;135602:6;135598:17;135591:35;135742:4;135734:6;135730:17;135720:27;;135776:1;135768:6;135761:17;135818:8;135811:4;135803:6;135799:17;135792:35;135950:4;135942:6;135938:17;135932:4;135925:31;135132:842;;;;;:::o;148609:108::-;148676:8;:6;:8::i;:::-;148668:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;148609:108::o;148424:::-;148495:8;:6;:8::i;:::-;148494:9;148486:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;148424:108::o;21210:148::-;21286:4;21325:25;21310:40;;;:11;:40;;;;21303:47;;21210:148;;;:::o;175621:450::-;175766:8;:6;:8::i;:::-;175762:79;;;175791:38;;;;;;;;;;:::i;:::-;;;;;;;;175762:79;175873:1;175857:18;;:4;:18;;;;:38;;;;;175893:1;175879:16;;:2;:16;;;;175857:38;175853:154;;;175920:11;:17;175932:4;175920:17;;;;;;;;;;;;;;;;;;;;;;;;;175912:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;175853:154;176027:36;176041:4;176047:2;176051:3;176056:6;176027:13;:36::i;:::-;175621:450;;;;:::o;16802:984::-;17026:1;17009:2;:14;;;:18;17005:774;;;17065:2;17048:38;;;17087:8;17097:4;17103:2;17107:5;17114:4;17048:71;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;17044:724;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17441:1;17424:6;:13;:18;17420:333;;17569:2;17531:41;;;;;;;;;;;:::i;:::-;;;;;;;;17420:333;17703:6;17697:13;17688:6;17684:2;17680:15;17673:38;17044:724;17181:43;;;17169:55;;;:8;:55;;;;17165:192;;17334:2;17296:41;;;;;;;;;;;:::i;:::-;;;;;;;;17165:192;17120:252;17005:774;16802:984;;;;;;:::o;18352:1053::-;18601:1;18584:2;:14;;;:18;18580:818;;;18640:2;18623:43;;;18667:8;18677:4;18683:3;18688:6;18696:4;18623:78;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;18619:768;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19060:1;19043:6;:13;:18;19039:333;;19188:2;19150:41;;;;;;;;;;;:::i;:::-;;;;;;;;19039:333;19322:6;19316:13;19307:6;19303:2;19299:15;19292:38;18619:768;18795:48;;;18783:60;;;:8;:60;;;;18779:197;;18953:2;18915:41;;;;;;;;;;;:::i;:::-;;;;;;;;18779:197;18702:289;18580:818;18352:1053;;;;;;:::o;126335:1315::-;126471:6;:13;126457:3;:10;:27;126453:119;;126534:3;:10;126546:6;:13;126508:52;;;;;;;;;;;;:::i;:::-;;;;;;;;126453:119;126584:16;126603:12;:10;:12::i;:::-;126584:31;;126633:9;126628:709;126652:3;:10;126648:1;:14;126628:709;;;126684:10;126697:25;126720:1;126697:3;:22;;:25;;;;:::i;:::-;126684:38;;126737:13;126753:28;126779:1;126753:6;:25;;:28;;;;:::i;:::-;126737:44;;126818:1;126802:18;;:4;:18;;;126798:429;;126841:19;126863:9;:13;126873:2;126863:13;;;;;;;;;;;:19;126877:4;126863:19;;;;;;;;;;;;;;;;126841:41;;126919:5;126905:11;:19;126901:131;;;126983:4;126989:11;127002:5;127009:2;126956:56;;;;;;;;;;;;;;:::i;:::-;;;;;;;;126901:131;127187:5;127173:11;:19;127151:9;:13;127161:2;127151:13;;;;;;;;;;;:19;127165:4;127151:19;;;;;;;;;;;;;;;:41;;;;126822:405;126798:429;127261:1;127247:16;;:2;:16;;;127243:83;;127305:5;127284:9;:13;127294:2;127284:13;;;;;;;;;;;:17;127298:2;127284:17;;;;;;;;;;;;;;;;:26;;;;;;;:::i;:::-;;;;;;;;127243:83;126669:668;;126664:3;;;;:::i;:::-;;;126628:709;;;;127367:1;127353:3;:10;:15;127349:294;;127385:10;127398:25;127421:1;127398:3;:22;;:25;;;;:::i;:::-;127385:38;;127438:13;127454:28;127480:1;127454:6;:25;;:28;;;;:::i;:::-;127438:44;;127533:2;127502:45;;127527:4;127502:45;;127517:8;127502:45;;;127537:2;127541:5;127502:45;;;;;;;:::i;:::-;;;;;;;;127370:189;;127349:294;;;127615:2;127585:46;;127609:4;127585:46;;127599:8;127585:46;;;127619:3;127624:6;127585:46;;;;;;;:::i;:::-;;;;;;;;127349:294;126442:1208;126335:1315;;;;:::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:329::-;3272:6;3321:2;3309:9;3300:7;3296:23;3292:32;3289:119;;;3327:79;;:::i;:::-;3289:119;3447:1;3472:53;3517:7;3508:6;3497:9;3493:22;3472:53;:::i;:::-;3462:63;;3418:117;3213:329;;;;:::o;3548:99::-;3600:6;3634:5;3628:12;3618:22;;3548:99;;;:::o;3653:169::-;3737:11;3771:6;3766:3;3759:19;3811:4;3806:3;3802:14;3787:29;;3653:169;;;;:::o;3828:246::-;3909:1;3919:113;3933:6;3930:1;3927:13;3919:113;;;4018:1;4013:3;4009:11;4003:18;3999:1;3994:3;3990:11;3983:39;3955:2;3952:1;3948:10;3943:15;;3919:113;;;4066:1;4057:6;4052:3;4048:16;4041:27;3890:184;3828:246;;;:::o;4080:102::-;4121:6;4172:2;4168:7;4163:2;4156:5;4152:14;4148:28;4138:38;;4080:102;;;:::o;4188:377::-;4276:3;4304:39;4337:5;4304:39;:::i;:::-;4359:71;4423:6;4418:3;4359:71;:::i;:::-;4352:78;;4439:65;4497:6;4492:3;4485:4;4478:5;4474:16;4439:65;:::i;:::-;4529:29;4551:6;4529:29;:::i;:::-;4524:3;4520:39;4513:46;;4280:285;4188:377;;;;:::o;4571:313::-;4684:4;4722:2;4711:9;4707:18;4699:26;;4771:9;4765:4;4761:20;4757:1;4746:9;4742:17;4735:47;4799:78;4872:4;4863:6;4799:78;:::i;:::-;4791:86;;4571:313;;;;:::o;4890:329::-;4949:6;4998:2;4986:9;4977:7;4973:23;4969:32;4966:119;;;5004:79;;:::i;:::-;4966:119;5124:1;5149:53;5194:7;5185:6;5174:9;5170:22;5149:53;:::i;:::-;5139:63;;5095:117;4890:329;;;;:::o;5225:77::-;5262:7;5291:5;5280:16;;5225:77;;;:::o;5308:122::-;5381:24;5399:5;5381:24;:::i;:::-;5374:5;5371:35;5361:63;;5420:1;5417;5410:12;5361:63;5308:122;:::o;5436:139::-;5482:5;5520:6;5507:20;5498:29;;5536:33;5563:5;5536:33;:::i;:::-;5436:139;;;;:::o;5581:329::-;5640:6;5689:2;5677:9;5668:7;5664:23;5660:32;5657:119;;;5695:79;;:::i;:::-;5657:119;5815:1;5840:53;5885:7;5876:6;5865:9;5861:22;5840:53;:::i;:::-;5830:63;;5786:117;5581:329;;;;:::o;5916:118::-;6003:24;6021:5;6003:24;:::i;:::-;5998:3;5991:37;5916:118;;:::o;6040:222::-;6133:4;6171:2;6160:9;6156:18;6148:26;;6184:71;6252:1;6241:9;6237:17;6228:6;6184:71;:::i;:::-;6040:222;;;;:::o;6268:117::-;6377:1;6374;6367:12;6391:180;6439:77;6436:1;6429:88;6536:4;6533:1;6526:15;6560:4;6557:1;6550:15;6577:281;6660:27;6682:4;6660:27;:::i;:::-;6652:6;6648:40;6790:6;6778:10;6775:22;6754:18;6742:10;6739:34;6736:62;6733:88;;;6801:18;;:::i;:::-;6733:88;6841:10;6837:2;6830:22;6620:238;6577:281;;:::o;6864:129::-;6898:6;6925:20;;:::i;:::-;6915:30;;6954:33;6982:4;6974:6;6954:33;:::i;:::-;6864:129;;;:::o;6999:311::-;7076:4;7166:18;7158:6;7155:30;7152:56;;;7188:18;;:::i;:::-;7152:56;7238:4;7230:6;7226:17;7218:25;;7298:4;7292;7288:15;7280:23;;6999:311;;;:::o;7316:117::-;7425:1;7422;7415:12;7456:710;7552:5;7577:81;7593:64;7650:6;7593:64;:::i;:::-;7577:81;:::i;:::-;7568:90;;7678:5;7707:6;7700:5;7693:21;7741:4;7734:5;7730:16;7723:23;;7794:4;7786:6;7782:17;7774:6;7770:30;7823:3;7815:6;7812:15;7809:122;;;7842:79;;:::i;:::-;7809:122;7957:6;7940:220;7974:6;7969:3;7966:15;7940:220;;;8049:3;8078:37;8111:3;8099:10;8078:37;:::i;:::-;8073:3;8066:50;8145:4;8140:3;8136:14;8129:21;;8016:144;8000:4;7995:3;7991:14;7984:21;;7940:220;;;7944:21;7558:608;;7456:710;;;;;:::o;8189:370::-;8260:5;8309:3;8302:4;8294:6;8290:17;8286:27;8276:122;;8317:79;;:::i;:::-;8276:122;8434:6;8421:20;8459:94;8549:3;8541:6;8534:4;8526:6;8522:17;8459:94;:::i;:::-;8450:103;;8266:293;8189:370;;;;:::o;8565:117::-;8674:1;8671;8664:12;8688:307;8749:4;8839:18;8831:6;8828:30;8825:56;;;8861:18;;:::i;:::-;8825:56;8899:29;8921:6;8899:29;:::i;:::-;8891:37;;8983:4;8977;8973:15;8965:23;;8688:307;;;:::o;9001:146::-;9098:6;9093:3;9088;9075:30;9139:1;9130:6;9125:3;9121:16;9114:27;9001:146;;;:::o;9153:423::-;9230:5;9255:65;9271:48;9312:6;9271:48;:::i;:::-;9255:65;:::i;:::-;9246:74;;9343:6;9336:5;9329:21;9381:4;9374:5;9370:16;9419:3;9410:6;9405:3;9401:16;9398:25;9395:112;;;9426:79;;:::i;:::-;9395:112;9516:54;9563:6;9558:3;9553;9516:54;:::i;:::-;9236:340;9153:423;;;;;:::o;9595:338::-;9650:5;9699:3;9692:4;9684:6;9680:17;9676:27;9666:122;;9707:79;;:::i;:::-;9666:122;9824:6;9811:20;9849:78;9923:3;9915:6;9908:4;9900:6;9896:17;9849:78;:::i;:::-;9840:87;;9656:277;9595:338;;;;:::o;9939:1509::-;10093:6;10101;10109;10117;10125;10174:3;10162:9;10153:7;10149:23;10145:33;10142:120;;;10181:79;;:::i;:::-;10142:120;10301:1;10326:53;10371:7;10362:6;10351:9;10347:22;10326:53;:::i;:::-;10316:63;;10272:117;10428:2;10454:53;10499:7;10490:6;10479:9;10475:22;10454:53;:::i;:::-;10444:63;;10399:118;10584:2;10573:9;10569:18;10556:32;10615:18;10607:6;10604:30;10601:117;;;10637:79;;:::i;:::-;10601:117;10742:78;10812:7;10803:6;10792:9;10788:22;10742:78;:::i;:::-;10732:88;;10527:303;10897:2;10886:9;10882:18;10869:32;10928:18;10920:6;10917:30;10914:117;;;10950:79;;:::i;:::-;10914:117;11055:78;11125:7;11116:6;11105:9;11101:22;11055:78;:::i;:::-;11045:88;;10840:303;11210:3;11199:9;11195:19;11182:33;11242:18;11234:6;11231:30;11228:117;;;11264:79;;:::i;:::-;11228:117;11369:62;11423:7;11414:6;11403:9;11399:22;11369:62;:::i;:::-;11359:72;;11153:288;9939:1509;;;;;;;;:::o;11454:474::-;11522:6;11530;11579:2;11567:9;11558:7;11554:23;11550:32;11547:119;;;11585:79;;:::i;:::-;11547:119;11705:1;11730:53;11775:7;11766:6;11755:9;11751:22;11730:53;:::i;:::-;11720:63;;11676:117;11832:2;11858:53;11903:7;11894:6;11883:9;11879:22;11858:53;:::i;:::-;11848:63;;11803:118;11454:474;;;;;:::o;11934:311::-;12011:4;12101:18;12093:6;12090:30;12087:56;;;12123:18;;:::i;:::-;12087:56;12173:4;12165:6;12161:17;12153:25;;12233:4;12227;12223:15;12215:23;;11934:311;;;:::o;12268:710::-;12364:5;12389:81;12405:64;12462:6;12405:64;:::i;:::-;12389:81;:::i;:::-;12380:90;;12490:5;12519:6;12512:5;12505:21;12553:4;12546:5;12542:16;12535:23;;12606:4;12598:6;12594:17;12586:6;12582:30;12635:3;12627:6;12624:15;12621:122;;;12654:79;;:::i;:::-;12621:122;12769:6;12752:220;12786:6;12781:3;12778:15;12752:220;;;12861:3;12890:37;12923:3;12911:10;12890:37;:::i;:::-;12885:3;12878:50;12957:4;12952:3;12948:14;12941:21;;12828:144;12812:4;12807:3;12803:14;12796:21;;12752:220;;;12756:21;12370:608;;12268:710;;;;;:::o;13001:370::-;13072:5;13121:3;13114:4;13106:6;13102:17;13098:27;13088:122;;13129:79;;:::i;:::-;13088:122;13246:6;13233:20;13271:94;13361:3;13353:6;13346:4;13338:6;13334:17;13271:94;:::i;:::-;13262:103;;13078:293;13001:370;;;;:::o;13377:894::-;13495:6;13503;13552:2;13540:9;13531:7;13527:23;13523:32;13520:119;;;13558:79;;:::i;:::-;13520:119;13706:1;13695:9;13691:17;13678:31;13736:18;13728:6;13725:30;13722:117;;;13758:79;;:::i;:::-;13722:117;13863:78;13933:7;13924:6;13913:9;13909:22;13863:78;:::i;:::-;13853:88;;13649:302;14018:2;14007:9;14003:18;13990:32;14049:18;14041:6;14038:30;14035:117;;;14071:79;;:::i;:::-;14035:117;14176:78;14246:7;14237:6;14226:9;14222:22;14176:78;:::i;:::-;14166:88;;13961:303;13377:894;;;;;:::o;14277:114::-;14344:6;14378:5;14372:12;14362:22;;14277:114;;;:::o;14397:184::-;14496:11;14530:6;14525:3;14518:19;14570:4;14565:3;14561:14;14546:29;;14397:184;;;;:::o;14587:132::-;14654:4;14677:3;14669:11;;14707:4;14702:3;14698:14;14690:22;;14587:132;;;:::o;14725:108::-;14802:24;14820:5;14802:24;:::i;:::-;14797:3;14790:37;14725:108;;:::o;14839:179::-;14908:10;14929:46;14971:3;14963:6;14929:46;:::i;:::-;15007:4;15002:3;14998:14;14984:28;;14839:179;;;;:::o;15024:113::-;15094:4;15126;15121:3;15117:14;15109:22;;15024:113;;;:::o;15173:732::-;15292:3;15321:54;15369:5;15321:54;:::i;:::-;15391:86;15470:6;15465:3;15391:86;:::i;:::-;15384:93;;15501:56;15551:5;15501:56;:::i;:::-;15580:7;15611:1;15596:284;15621:6;15618:1;15615:13;15596:284;;;15697:6;15691:13;15724:63;15783:3;15768:13;15724:63;:::i;:::-;15717:70;;15810:60;15863:6;15810:60;:::i;:::-;15800:70;;15656:224;15643:1;15640;15636:9;15631:14;;15596:284;;;15600:14;15896:3;15889:10;;15297:608;;;15173:732;;;;:::o;15911:373::-;16054:4;16092:2;16081:9;16077:18;16069:26;;16141:9;16135:4;16131:20;16127:1;16116:9;16112:17;16105:47;16169:108;16272:4;16263:6;16169:108;:::i;:::-;16161:116;;15911:373;;;;:::o;16290:116::-;16360:21;16375:5;16360:21;:::i;:::-;16353:5;16350:32;16340:60;;16396:1;16393;16386:12;16340:60;16290:116;:::o;16412:133::-;16455:5;16493:6;16480:20;16471:29;;16509:30;16533:5;16509:30;:::i;:::-;16412:133;;;;:::o;16551:468::-;16616:6;16624;16673:2;16661:9;16652:7;16648:23;16644:32;16641:119;;;16679:79;;:::i;:::-;16641:119;16799:1;16824:53;16869:7;16860:6;16849:9;16845:22;16824:53;:::i;:::-;16814:63;;16770:117;16926:2;16952:50;16994:7;16985:6;16974:9;16970:22;16952:50;:::i;:::-;16942:60;;16897:115;16551:468;;;;;:::o;17025:474::-;17093:6;17101;17150:2;17138:9;17129:7;17125:23;17121:32;17118:119;;;17156:79;;:::i;:::-;17118:119;17276:1;17301:53;17346:7;17337:6;17326:9;17322:22;17301:53;:::i;:::-;17291:63;;17247:117;17403:2;17429:53;17474:7;17465:6;17454:9;17450:22;17429:53;:::i;:::-;17419:63;;17374:118;17025:474;;;;;:::o;17505:308::-;17567:4;17657:18;17649:6;17646:30;17643:56;;;17679:18;;:::i;:::-;17643:56;17717:29;17739:6;17717:29;:::i;:::-;17709:37;;17801:4;17795;17791:15;17783:23;;17505:308;;;:::o;17819:425::-;17897:5;17922:66;17938:49;17980:6;17938:49;:::i;:::-;17922:66;:::i;:::-;17913:75;;18011:6;18004:5;17997:21;18049:4;18042:5;18038:16;18087:3;18078:6;18073:3;18069:16;18066:25;18063:112;;;18094:79;;:::i;:::-;18063:112;18184:54;18231:6;18226:3;18221;18184:54;:::i;:::-;17903:341;17819:425;;;;;:::o;18264:340::-;18320:5;18369:3;18362:4;18354:6;18350:17;18346:27;18336:122;;18377:79;;:::i;:::-;18336:122;18494:6;18481:20;18519:79;18594:3;18586:6;18579:4;18571:6;18567:17;18519:79;:::i;:::-;18510:88;;18326:278;18264:340;;;;:::o;18610:509::-;18679:6;18728:2;18716:9;18707:7;18703:23;18699:32;18696:119;;;18734:79;;:::i;:::-;18696:119;18882:1;18871:9;18867:17;18854:31;18912:18;18904:6;18901:30;18898:117;;;18934:79;;:::i;:::-;18898:117;19039:63;19094:7;19085:6;19074:9;19070:22;19039:63;:::i;:::-;19029:73;;18825:287;18610:509;;;;:::o;19125:1089::-;19229:6;19237;19245;19253;19261;19310:3;19298:9;19289:7;19285:23;19281:33;19278:120;;;19317:79;;:::i;:::-;19278:120;19437:1;19462:53;19507:7;19498:6;19487:9;19483:22;19462:53;:::i;:::-;19452:63;;19408:117;19564:2;19590:53;19635:7;19626:6;19615:9;19611:22;19590:53;:::i;:::-;19580:63;;19535:118;19692:2;19718:53;19763:7;19754:6;19743:9;19739:22;19718:53;:::i;:::-;19708:63;;19663:118;19820:2;19846:53;19891:7;19882:6;19871:9;19867:22;19846:53;:::i;:::-;19836:63;;19791:118;19976:3;19965:9;19961:19;19948:33;20008:18;20000:6;19997:30;19994:117;;;20030:79;;:::i;:::-;19994:117;20135:62;20189:7;20180:6;20169:9;20165:22;20135:62;:::i;:::-;20125:72;;19919:288;19125:1089;;;;;;;;:::o;20220:237::-;20360:34;20356:1;20348:6;20344:14;20337:58;20429:20;20424:2;20416:6;20412:15;20405:45;20220:237;:::o;20463:366::-;20605:3;20626:67;20690:2;20685:3;20626:67;:::i;:::-;20619:74;;20702:93;20791:3;20702:93;:::i;:::-;20820:2;20815:3;20811:12;20804:19;;20463:366;;;:::o;20835:419::-;21001:4;21039:2;21028:9;21024:18;21016:26;;21088:9;21082:4;21078:20;21074:1;21063:9;21059:17;21052:47;21116:131;21242:4;21116:131;:::i;:::-;21108:139;;20835:419;;;:::o;21260:148::-;21362:11;21399:3;21384:18;;21260:148;;;;:::o;21414:161::-;21554:9;21550:1;21542:6;21538:14;21531:33;21414:161;:::o;21585:416::-;21745:3;21770:84;21852:1;21847:3;21770:84;:::i;:::-;21763:91;;21867:93;21956:3;21867:93;:::i;:::-;21989:1;21984:3;21980:11;21973:18;;21585:416;;;:::o;22011:196::-;22063:77;22060:1;22053:88;22164:4;22161:1;22154:15;22192:4;22189:1;22182:15;22217:356;22261:6;22302:1;22296:4;22292:12;22282:22;;22353:1;22347:4;22343:12;22378:18;22368:89;;22438:4;22430:6;22426:17;22416:27;;22368:89;22508:2;22500:6;22497:14;22477:18;22474:38;22471:92;;22531:18;;:::i;:::-;22471:92;22268:305;22217:356;;;:::o;22583:157::-;22632:4;22659:3;22651:11;;22686:3;22683:1;22676:14;22724:4;22721:1;22711:18;22703:26;;22583:157;;;:::o;22778:954::-;22881:3;22922:5;22916:12;22955:36;22981:9;22955:36;:::i;:::-;23011:89;23093:6;23088:3;23011:89;:::i;:::-;23004:96;;23135:1;23124:9;23120:17;23155:1;23150:182;;;;23350:1;23345:377;;;;23113:609;;23150:182;23242:4;23238:9;23227;23223:25;23218:3;23211:38;23308:6;23301:14;23294:22;23286:6;23282:35;23277:3;23273:45;23266:52;;23150:182;;23345:377;23420:38;23452:5;23420:38;:::i;:::-;23484:1;23502:166;23516:6;23513:1;23510:13;23502:166;;;23594:7;23588:14;23584:1;23579:3;23575:11;23568:35;23648:1;23639:7;23635:15;23624:26;;23538:4;23535:1;23531:12;23526:17;;23502:166;;;23701:6;23696:3;23692:16;23685:23;;23352:370;;23113:609;;22885:847;;22778:954;;;;:::o;23742:551::-;23972:3;23998:148;24142:3;23998:148;:::i;:::-;23991:155;;24167:92;24255:3;24246:6;24167:92;:::i;:::-;24160:99;;24280:3;24273:10;;23742:551;;;;:::o;24303:126::-;24394:24;24412:5;24394:24;:::i;:::-;24389:3;24382:37;24303:126;;:::o;24439:348::-;24560:4;24602:2;24591:9;24587:18;24579:26;;24619:71;24687:1;24676:9;24672:17;24663:6;24619:71;:::i;:::-;24704:72;24772:2;24761:9;24757:18;24748:6;24704:72;:::i;:::-;24439:348;;;;;:::o;24797:248::-;24941:34;24937:1;24929:6;24925:14;24918:58;25014:19;25009:2;25001:6;24997:15;24990:44;24797:248;:::o;25055:382::-;25197:3;25222:67;25286:2;25281:3;25222:67;:::i;:::-;25215:74;;25302:93;25391:3;25302:93;:::i;:::-;25424:2;25419:3;25415:12;25408:19;;25055:382;;;:::o;25447:435::-;25613:4;25655:2;25644:9;25640:18;25632:26;;25708:9;25702:4;25698:20;25694:1;25683:9;25679:17;25672:47;25740:131;25866:4;25740:131;:::i;:::-;25732:139;;25447:435;;;:::o;25892:187::-;26036:31;26032:1;26024:6;26020:14;26013:55;25892:187;:::o;26089:382::-;26231:3;26256:67;26320:2;26315:3;26256:67;:::i;:::-;26249:74;;26336:93;26425:3;26336:93;:::i;:::-;26458:2;26453:3;26449:12;26442:19;;26089:382;;;:::o;26481:435::-;26647:4;26689:2;26678:9;26674:18;26666:26;;26742:9;26736:4;26732:20;26728:1;26717:9;26713:17;26706:47;26774:131;26900:4;26774:131;:::i;:::-;26766:139;;26481:435;;;:::o;26926:348::-;27047:4;27089:2;27078:9;27074:18;27066:26;;27106:71;27174:1;27163:9;27159:17;27150:6;27106:71;:::i;:::-;27191:72;27259:2;27248:9;27244:18;27235:6;27191:72;:::i;:::-;26926:348;;;;;:::o;27284:196::-;27336:77;27333:1;27326:88;27437:4;27434:1;27427:15;27465:4;27462:1;27455:15;27490:196;27542:77;27539:1;27532:88;27643:4;27640:1;27633:15;27671:4;27668:1;27661:15;27696:249;27735:3;27762:24;27780:5;27762:24;:::i;:::-;27753:33;;27812:66;27805:5;27802:77;27799:103;;27882:18;;:::i;:::-;27799:103;27933:1;27926:5;27922:13;27915:20;;27696:249;;;:::o;27955:188::-;28099:32;28095:1;28087:6;28083:14;28076:56;27955:188;:::o;28153:382::-;28295:3;28320:67;28384:2;28379:3;28320:67;:::i;:::-;28313:74;;28400:93;28489:3;28400:93;:::i;:::-;28522:2;28517:3;28513:12;28506:19;;28153:382;;;:::o;28545:435::-;28711:4;28753:2;28742:9;28738:18;28730:26;;28806:9;28800:4;28796:20;28792:1;28781:9;28777:17;28770:47;28838:131;28964:4;28838:131;:::i;:::-;28830:139;;28545:435;;;:::o;28990:101::-;29027:6;29078:2;29073;29066:5;29062:14;29058:23;29048:33;;28990:101;;;:::o;29101:119::-;29145:8;29203:5;29197:4;29193:16;29168:41;;29101:119;;;;:::o;29230:417::-;29299:6;29353:1;29341:10;29337:18;29380:97;29410:66;29399:9;29380:97;:::i;:::-;29502:39;29532:8;29521:9;29502:39;:::i;:::-;29490:51;;29578:4;29574:9;29567:5;29563:21;29554:30;;29631:4;29621:8;29617:19;29610:5;29607:30;29597:40;;29306:341;;29230:417;;;;;:::o;29657:68::-;29685:3;29710:5;29703:12;;29657:68;;;:::o;29735:150::-;29785:9;29822:53;29840:34;29849:24;29867:5;29849:24;:::i;:::-;29840:34;:::i;:::-;29822:53;:::i;:::-;29809:66;;29735:150;;;:::o;29895:83::-;29938:3;29963:5;29956:12;;29895:83;;;:::o;29988:281::-;30102:39;30133:7;30102:39;:::i;:::-;30167:91;30216:41;30240:16;30216:41;:::i;:::-;30208:6;30201:4;30195:11;30167:91;:::i;:::-;30161:4;30154:105;30064:205;29988:281;;;:::o;30279:81::-;30324:3;30279:81;:::o;30370:201::-;30451:32;;:::i;:::-;30496:65;30554:6;30546;30540:4;30496:65;:::i;:::-;30423:148;30370:201;;:::o;30581:206::-;30645:132;30662:3;30655:5;30652:14;30645:132;;;30724:39;30761:1;30754:5;30724:39;:::i;:::-;30689:1;30682:5;30678:13;30669:22;;30645:132;;;30581:206;;:::o;30797:575::-;30902:2;30897:3;30894:11;30891:470;;;30940:38;30972:5;30940:38;:::i;:::-;31028:29;31046:10;31028:29;:::i;:::-;31018:8;31014:44;31219:2;31207:10;31204:18;31201:49;;;31240:8;31225:23;;31201:49;31267:80;31323:22;31341:3;31323:22;:::i;:::-;31313:8;31309:37;31296:11;31267:80;:::i;:::-;30906:455;;30891:470;30797:575;;;:::o;31382:129::-;31436:8;31494:5;31488:4;31484:16;31459:41;;31382:129;;;;:::o;31521:181::-;31565:6;31602:51;31650:1;31646:6;31638:5;31635:1;31631:13;31602:51;:::i;:::-;31598:56;31687:4;31681;31677:15;31667:25;;31572:130;31521:181;;;;:::o;31711:315::-;31787:4;31945:29;31970:3;31964:4;31945:29;:::i;:::-;31937:37;;32011:3;32008:1;32004:11;31998:4;31995:21;31987:29;;31711:315;;;;:::o;32035:1523::-;32156:37;32189:3;32156:37;:::i;:::-;32266:18;32258:6;32255:30;32252:56;;;32288:18;;:::i;:::-;32252:56;32336:38;32368:4;32362:11;32336:38;:::i;:::-;32429:67;32489:6;32481;32475:4;32429:67;:::i;:::-;32527:1;32555:4;32542:17;;32591:2;32583:6;32580:14;32612:1;32607:674;;;;33333:1;33354:6;33351:85;;;33407:9;33402:3;33398:19;33392:26;33383:35;;33351:85;33466:67;33526:6;33519:5;33466:67;:::i;:::-;33460:4;33453:81;33302:246;32573:975;;32607:674;32663:4;32659:9;32651:6;32647:22;32701:37;32733:4;32701:37;:::i;:::-;32764:1;32782:224;32796:7;32793:1;32790:14;32782:224;;;32879:9;32874:3;32870:19;32864:26;32856:6;32849:42;32934:1;32926:6;32922:14;32912:24;;32985:2;32974:9;32970:18;32957:31;;32819:4;32816:1;32812:12;32807:17;;32782:224;;;33038:6;33029:7;33026:19;33023:191;;;33100:9;33095:3;33091:19;33085:26;33147:48;33189:4;33181:6;33177:17;33166:9;33147:48;:::i;:::-;33139:6;33132:64;33046:168;33023:191;33264:1;33260;33252:6;33248:14;33244:22;33238:4;33231:36;32614:667;;;32573:975;;32127:1431;;;32035:1523;;:::o;33568:234::-;33661:4;33703:2;33692:9;33688:18;33680:26;;33720:71;33788:1;33777:9;33773:17;33764:6;33720:71;:::i;:::-;33568:234;;;;:::o;33812:348::-;33933:4;33975:2;33964:9;33960:18;33952:26;;33992:71;34060:1;34049:9;34045:17;34036:6;33992:71;:::i;:::-;34077:72;34145:2;34134:9;34130:18;34121:6;34077:72;:::i;:::-;33812:348;;;;;:::o;34170:178::-;34314:22;34310:1;34302:6;34298:14;34291:46;34170:178;:::o;34358:382::-;34500:3;34525:67;34589:2;34584:3;34525:67;:::i;:::-;34518:74;;34605:93;34694:3;34605:93;:::i;:::-;34727:2;34722:3;34718:12;34711:19;;34358:382;;;:::o;34750:435::-;34916:4;34958:2;34947:9;34943:18;34935:26;;35011:9;35005:4;35001:20;34997:1;34986:9;34982:17;34975:47;35043:131;35169:4;35043:131;:::i;:::-;35035:139;;34750:435;;;:::o;35195:174::-;35339:18;35335:1;35327:6;35323:14;35316:42;35195:174;:::o;35379:382::-;35521:3;35546:67;35610:2;35605:3;35546:67;:::i;:::-;35539:74;;35626:93;35715:3;35626:93;:::i;:::-;35748:2;35743:3;35739:12;35732:19;;35379:382;;;:::o;35771:435::-;35937:4;35979:2;35968:9;35964:18;35956:26;;36032:9;36026:4;36022:20;36018:1;36007:9;36003:17;35996:47;36064:131;36190:4;36064:131;:::i;:::-;36056:139;;35771:435;;;:::o;36216:186::-;36360:30;36356:1;36348:6;36344:14;36337:54;36216:186;:::o;36412:382::-;36554:3;36579:67;36643:2;36638:3;36579:67;:::i;:::-;36572:74;;36659:93;36748:3;36659:93;:::i;:::-;36781:2;36776:3;36772:12;36765:19;;36412:382;;;:::o;36804:435::-;36970:4;37012:2;37001:9;36997:18;36989:26;;37065:9;37059:4;37055:20;37051:1;37040:9;37036:17;37029:47;37097:131;37223:4;37097:131;:::i;:::-;37089:139;;36804:435;;;:::o;37249:252::-;37393:34;37389:1;37381:6;37377:14;37370:58;37466:23;37461:2;37453:6;37449:15;37442:48;37249:252;:::o;37511:382::-;37653:3;37678:67;37742:2;37737:3;37678:67;:::i;:::-;37671:74;;37758:93;37847:3;37758:93;:::i;:::-;37880:2;37875:3;37871:12;37864:19;;37511:382;;;:::o;37903:435::-;38069:4;38111:2;38100:9;38096:18;38088:26;;38164:9;38158:4;38154:20;38150:1;38139:9;38135:17;38128:47;38196:131;38322:4;38196:131;:::i;:::-;38188:139;;37903:435;;;:::o;38348:106::-;38399:6;38437:5;38431:12;38421:22;;38348:106;;;:::o;38464:180::-;38547:11;38585:6;38580:3;38573:19;38629:4;38624:3;38620:14;38605:29;;38464:180;;;;:::o;38654:393::-;38740:3;38772:38;38804:5;38772:38;:::i;:::-;38830:70;38893:6;38888:3;38830:70;:::i;:::-;38823:77;;38913:65;38971:6;38966:3;38959:4;38952:5;38948:16;38913:65;:::i;:::-;39007:29;39029:6;39007:29;:::i;:::-;39002:3;38998:39;38991:46;;38744:303;38654:393;;;;:::o;39057:783::-;39280:4;39322:3;39311:9;39307:19;39299:27;;39340:71;39408:1;39397:9;39393:17;39384:6;39340:71;:::i;:::-;39425:72;39493:2;39482:9;39478:18;39469:6;39425:72;:::i;:::-;39511;39579:2;39568:9;39564:18;39555:6;39511:72;:::i;:::-;39597;39665:2;39654:9;39650:18;39641:6;39597:72;:::i;:::-;39721:9;39715:4;39711:20;39705:3;39694:9;39690:19;39683:49;39753:76;39824:4;39815:6;39753:76;:::i;:::-;39745:84;;39057:783;;;;;;;;:::o;39850:153::-;39906:5;39941:6;39935:13;39926:22;;39961:32;39987:5;39961:32;:::i;:::-;39850:153;;;;:::o;40013:373::-;40082:6;40135:2;40123:9;40114:7;40110:23;40106:32;40103:119;;;40141:79;;:::i;:::-;40103:119;40269:1;40298:63;40353:7;40344:6;40333:9;40329:22;40298:63;:::i;:::-;40288:73;;40236:139;40013:373;;;;:::o;40396:1093::-;40719:4;40761:3;40750:9;40746:19;40738:27;;40779:71;40847:1;40836:9;40832:17;40823:6;40779:71;:::i;:::-;40864:72;40932:2;40921:9;40917:18;40908:6;40864:72;:::i;:::-;40987:9;40981:4;40977:20;40972:2;40961:9;40957:18;40950:48;41019:108;41122:4;41113:6;41019:108;:::i;:::-;41011:116;;41178:9;41172:4;41168:20;41163:2;41152:9;41148:18;41141:48;41210:108;41313:4;41304:6;41210:108;:::i;:::-;41202:116;;41370:9;41364:4;41360:20;41354:3;41343:9;41339:19;41332:49;41402:76;41473:4;41464:6;41402:76;:::i;:::-;41394:84;;40396:1093;;;;;;;;:::o;41499:577::-;41676:4;41718:3;41707:9;41703:19;41695:27;;41736:71;41804:1;41793:9;41789:17;41780:6;41736:71;:::i;:::-;41821:72;41889:2;41878:9;41874:18;41865:6;41821:72;:::i;:::-;41907;41975:2;41964:9;41960:18;41951:6;41907:72;:::i;:::-;41993;42061:2;42050:9;42046:18;42037:6;41993:72;:::i;:::-;41499:577;;;;;;;:::o;42086:211::-;42126:3;42149:20;42167:1;42149:20;:::i;:::-;42144:25;;42187:20;42205:1;42187:20;:::i;:::-;42182:25;;42234:1;42231;42227:9;42220:16;;42259:3;42256:1;42253:10;42250:36;;;42266:18;;:::i;:::-;42250:36;42086:211;;;;:::o;42307:658::-;42528:4;42570:2;42559:9;42555:18;42547:26;;42623:9;42617:4;42613:20;42609:1;42598:9;42594:17;42587:47;42655:108;42758:4;42749:6;42655:108;:::i;:::-;42647:116;;42814:9;42808:4;42804:20;42799:2;42788:9;42784:18;42777:48;42846:108;42949:4;42940:6;42846:108;:::i;:::-;42838:116;;42307:658;;;;;:::o
Swarm Source
ipfs://65b8cecd23c2275e57badbbb0e21b7accb3212423230a3654240a74bb53448b4
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 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.