Source Code
Overview
POL Balance
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
EpisMintSiteNFT
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "./EpisMintSiteBase.sol"; contract EpisMintSiteNFT is EpisMintSiteBase { mapping(uint256 => string) private _tokenURIs; event TokenRegistered( address indexed signer, uint256 indexed tokenId, string tokenURI ); event NFTMetadataUpdated( uint256 indexed tokenId, string tokenURI, address signer ); event NFTMint( address indexed to, uint256 indexed tokenId, uint256 amount, address signer ); event NFTBurn( address indexed from, uint256 indexed tokenId, uint256 amount, address signer ); event NFTForceTransfer( address indexed from, address indexed to, uint256 indexed tokenId, address signer ); /** * @dev コントラクトのコンストラクタ * @param _name コントラクトの名前 * @param _symbol コントラクトのシンボル * @param _multicallContract マルチコールコントラクトのアドレス */ function initialize( string memory _name, string memory _symbol, address _multicallContract ) public initializer { __EpisMintSiteBase_init(_name, _symbol, _multicallContract); } /** * @dev 新しいNFTトークン情報を登録します。 * @param tokenId 登録するトークンID * @param tokenURI 登録するトークン情報 * @param timestamp 署名時のUNIXタイムスタンプ * @param signature adminによる署名データ * @return 登録されたトークンID */ function registerNFT( uint256 tokenId, string memory tokenURI, uint256 timestamp, bytes memory signature ) external returns (uint256) { address signer = verifySignature( abi.encodePacked(tokenId, tokenURI, timestamp), signature, Role.Admin ); require(bytes(tokenURI).length > 0, "Token URI cannot be empty"); require(!tokenExists(tokenId), "Token ID already exists"); _tokenURIs[tokenId] = tokenURI; emit TokenRegistered(signer, tokenId, tokenURI); return tokenId; } function setURI( uint256 tokenId, string memory newuri, uint256 timestamp, bytes memory signature ) external { verifySignature( abi.encodePacked(tokenId, newuri, timestamp), signature, Role.Admin ); require(bytes(newuri).length > 0, "URI cannot be empty"); require( tokenExists(tokenId), "ERC1155Metadata: URI set of nonexistent token" ); _tokenURIs[tokenId] = newuri; emit URI(newuri, tokenId); } function mintNFT( address to, uint256 tokenId, uint256 timestamp, bytes memory signature ) external returns (uint256) { address signer = verifySignature( abi.encodePacked(to, tokenId, timestamp), signature, Role.Admin ); require(!bannedUsers[to], "Recipient banned"); require(tokenExists(tokenId), "Token not registered"); require(balanceOf(to, tokenId) == 0, "User already owns this token"); _mint(to, tokenId, 1, ""); emit NFTMint(to, tokenId, 1, signer); return tokenId; } /** * @dev NFTをバーンします * @param from バーン元のアドレス * @param tokenId バーンするトークンのID * @param timestamp 署名時のUNIXタイムスタンプ * @param signature superAdminによる署名データ */ function burnNFT( address from, uint256 tokenId, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(from, tokenId, timestamp), signature, Role.SuperAdmin ); require( balanceOf(from, tokenId) >= 1, "Token not owned by from address" ); _burn(from, tokenId, 1); emit NFTBurn(from, tokenId, 1, signer); } /** * @dev NFTを強制的に転送します * @param from 送信元アドレス * @param to 送信先アドレス * @param tokenId 転送するトークンID * @param data 追加データ * @param timestamp 署名時のUNIXタイムスタンプ * @param signature superAdminによる署名データ */ function forceTransferNFT( address from, address to, uint256 tokenId, bytes memory data, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(from, to, tokenId, timestamp), signature, Role.SuperAdmin ); require( balanceOf(from, tokenId) >= 1, "Token not owned by from address" ); require( balanceOf(to, tokenId) == 0, "Recipient already owns this token" ); _safeTransferFrom(from, to, tokenId, 1, data); emit NFTForceTransfer(from, to, tokenId, signer); } /** * @dev トークンのURIを取得します * @param tokenId 取得するトークンのID * @return トークンのURI */ function uri(uint256 tokenId) public view override returns (string memory) { require( tokenExists(tokenId), "ERC1155Metadata: URI query for nonexistent token" ); return _tokenURIs[tokenId]; } /** * @dev トークンの存在を確認します * @param tokenId 確認するトークンのID * @return トークンの存在 */ function tokenExists(uint256 tokenId) public view returns (bool) { return bytes(_tokenURIs[tokenId]).length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.20; import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol"; import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; import {Initializable} from "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC1967-compliant implementation pointing to self. * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.20; import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; import {IERC1155MetadataURI} from "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol"; import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {ERC165Upgradeable} from "../../utils/introspection/ERC165Upgradeable.sol"; import {Arrays} from "@openzeppelin/contracts/utils/Arrays.sol"; import {IERC1155Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @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 ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155, IERC1155MetadataURI, IERC1155Errors { using Arrays for uint256[]; using Arrays for address[]; /// @custom:storage-location erc7201:openzeppelin.storage.ERC1155 struct ERC1155Storage { mapping(uint256 id => mapping(address account => uint256)) _balances; mapping(address account => mapping(address operator => bool)) _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string _uri; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC1155")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ERC1155StorageLocation = 0x88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4500; function _getERC1155Storage() private pure returns (ERC1155Storage storage $) { assembly { $.slot := ERC1155StorageLocation } } /** * @dev See {_setURI}. */ function __ERC1155_init(string memory uri_) internal onlyInitializing { __ERC1155_init_unchained(uri_); } function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, 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 EIP]. * * 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) { ERC1155Storage storage $ = _getERC1155Storage(); return $._uri; } /** * @dev See {IERC1155-balanceOf}. */ function balanceOf(address account, uint256 id) public view virtual returns (uint256) { ERC1155Storage storage $ = _getERC1155Storage(); 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) { ERC1155Storage storage $ = _getERC1155Storage(); 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 { ERC1155Storage storage $ = _getERC1155Storage(); 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); _doSafeTransferAcceptanceCheck(operator, from, to, id, value, data); } else { _doSafeBatchTransferAcceptanceCheck(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 EIP]. * * 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 { ERC1155Storage storage $ = _getERC1155Storage(); $._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 { ERC1155Storage storage $ = _getERC1155Storage(); if (operator == address(0)) { revert ERC1155InvalidOperator(address(0)); } $._operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Performs an acceptance check by calling {IERC1155-onERC1155Received} on the `to` address * if it contains code at the moment of execution. */ function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 value, bytes memory data ) private { 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 ERC1155InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-ERC1155Receiver implementer revert ERC1155InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } } /** * @dev Performs a batch acceptance check by calling {IERC1155-onERC1155BatchReceived} on the `to` address * if it contains code at the moment of execution. */ function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) private { 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 ERC1155InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-ERC1155Receiver implementer revert ERC1155InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } } /** * @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) { /// @solidity memory-safe-assembly assembly { // 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)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Supply.sol) pragma solidity ^0.8.20; import {ERC1155Upgradeable} from "../ERC1155Upgradeable.sol"; import {Initializable} from "../../../proxy/utils/Initializable.sol"; /** * @dev Extension of ERC1155 that adds tracking of total supply per id. * * Useful for scenarios where Fungible and Non-fungible tokens have to be * clearly identified. Note: While a totalSupply of 1 might mean the * corresponding is an NFT, there is no guarantees that no other token with the * same id are not going to be minted. * * NOTE: This contract implies a global limit of 2**256 - 1 to the number of tokens * that can be minted. * * CAUTION: This extension should not be added in an upgrade to an already deployed contract. */ abstract contract ERC1155SupplyUpgradeable is Initializable, ERC1155Upgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.ERC1155Supply struct ERC1155SupplyStorage { mapping(uint256 id => uint256) _totalSupply; uint256 _totalSupplyAll; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC1155Supply")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ERC1155SupplyStorageLocation = 0x4a593662ee04d27b6a00ebb31be7fe0c102c2ade82a7c5d764f2df05dc4e2800; function _getERC1155SupplyStorage() private pure returns (ERC1155SupplyStorage storage $) { assembly { $.slot := ERC1155SupplyStorageLocation } } function __ERC1155Supply_init() internal onlyInitializing { } function __ERC1155Supply_init_unchained() internal onlyInitializing { } /** * @dev Total value of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { ERC1155SupplyStorage storage $ = _getERC1155SupplyStorage(); return $._totalSupply[id]; } /** * @dev Total value of tokens. */ function totalSupply() public view virtual returns (uint256) { ERC1155SupplyStorage storage $ = _getERC1155SupplyStorage(); return $._totalSupplyAll; } /** * @dev Indicates whether any token exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return totalSupply(id) > 0; } /** * @dev See {ERC1155-_update}. */ function _update( address from, address to, uint256[] memory ids, uint256[] memory values ) internal virtual override { ERC1155SupplyStorage storage $ = _getERC1155SupplyStorage(); super._update(from, to, ids, values); if (from == address(0)) { uint256 totalMintValue = 0; for (uint256 i = 0; i < ids.length; ++i) { uint256 value = values[i]; // Overflow check required: The rest of the code assumes that totalSupply never overflows $._totalSupply[ids[i]] += value; totalMintValue += value; } // Overflow check required: The rest of the code assumes that totalSupplyAll never overflows $._totalSupplyAll += totalMintValue; } if (to == address(0)) { uint256 totalBurnValue = 0; for (uint256 i = 0; i < ids.length; ++i) { uint256 value = values[i]; unchecked { // Overflow not possible: values[i] <= balanceOf(from, ids[i]) <= totalSupply(ids[i]) $._totalSupply[ids[i]] -= value; // Overflow not possible: sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll totalBurnValue += value; } } unchecked { // Overflow not possible: totalBurnValue = sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll $._totalSupplyAll -= totalBurnValue; } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } 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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 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 ERC165Upgradeable is Initializable, IERC165 { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 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 ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-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 ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.20; import {IBeacon} from "../beacon/IBeacon.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. */ library ERC1967Utils { // We re-declare ERC-1967 events here because they can't be used directly from IERC1967. // This will be fixed in Solidity 0.8.21. At that point we should remove these events. /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.20; import {IERC1155} from "../IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. */ 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. */ 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`. * * Requirements: * * - `account` cannot be the zero address. */ 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 caller. */ 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 {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 {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; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @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 ERC1155 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 ERC1155 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Arrays.sol) pragma solidity ^0.8.20; import {StorageSlot} from "./StorageSlot.sol"; import {Math} from "./math/Math.sol"; /** * @dev Collection of functions related to array types. */ library Arrays { using StorageSlot for bytes32; /** * @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). * * `array` is expected to be sorted in ascending order, and to contain no * repeated elements. */ 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 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; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.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; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.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; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.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(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * 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[EIP 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return 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. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. 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^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // 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^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice 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) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return 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 { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.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 ERC1967 implementation slot: * ```solidity * contract ERC1967 { * 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; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 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) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { 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) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { 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) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev 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; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { 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 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)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155SupplyUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; contract EpisMintSiteBase is ERC1155SupplyUpgradeable, UUPSUpgradeable { using ECDSA for bytes32; using MessageHashUtils for bytes32; enum Role { SuperAdmin, Admin, ContractAdmin } string public name; string public symbol; address public SELF_ADDRESS; address public contractAdmin; address public multicallContract; uint256 public superAdminCount; uint256 public maxSuperAdmins; mapping(address => bool) public bannedUsers; mapping(address => bool) public superAdmins; mapping(address => bool) public admins; mapping(bytes32 => bool) public usedSignatures; event ContractAdminTransferred( address indexed oldContractAdmin, address indexed newContractAdmin ); event ContractUpgradeAuthorized( address newImplementation, address signer, address executor ); event MulticallContractUpdated( address newMulticallContract, address signer ); event SuperAdminAdded( address indexed newSuperAdmin, address indexed signer ); event SuperAdminRemoved(address indexed superAdmin, address indexed signer); event MaxSuperAdminsUpdated(uint256 newMaxSuperAdmins, address signer); event AdminAdded(address indexed newAdmin, address indexed signer); event AdminRemoved(address indexed admin, address indexed signer); event UserBanned(address indexed user, address indexed signer); event UserUnbanned(address indexed user, address indexed signer); function __EpisMintSiteBase_init( string memory _name, string memory _symbol, address _multicallContract ) internal initializer { __ERC1155_init(""); __ERC1155Supply_init(); __UUPSUpgradeable_init(); SELF_ADDRESS = address(this); contractAdmin = msg.sender; name = _name; symbol = _symbol; multicallContract = _multicallContract; maxSuperAdmins = 2; } function transferContractAdmin( address newContractAdmin, uint256 timestamp, bytes memory signature ) external { require( newContractAdmin != address(0), "New contractAdmin cannot be zero address" ); verifySignature( abi.encodePacked(newContractAdmin, timestamp), signature, Role.ContractAdmin ); address oldContractAdmin = contractAdmin; contractAdmin = newContractAdmin; emit ContractAdminTransferred(oldContractAdmin, newContractAdmin); } function upgradeContract( address newImplementation, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(newImplementation, timestamp), signature, Role.ContractAdmin ); emit ContractUpgradeAuthorized(newImplementation, signer, msg.sender); upgradeToAndCall(newImplementation, new bytes(0)); } function addSuperAdmin( address newSuperAdmin, uint256 timestamp, bytes memory signature ) external { address signer; if (superAdminCount == 0) { require( msg.sender == contractAdmin, "Only deployer can add the first super admin" ); signer = contractAdmin; } else { signer = verifySignature( abi.encodePacked(newSuperAdmin, timestamp), signature, Role.SuperAdmin ); } require( superAdminCount < maxSuperAdmins, "Maximum number of super admins reached" ); require( !superAdmins[newSuperAdmin], "Address is already a super admin" ); superAdmins[newSuperAdmin] = true; admins[newSuperAdmin] = true; superAdminCount++; emit SuperAdminAdded(newSuperAdmin, signer); emit AdminAdded(newSuperAdmin, signer); } function removeSuperAdmin( address superAdmin, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(superAdmin, timestamp), signature, Role.SuperAdmin ); require(superAdmins[superAdmin], "Address is not a super admin"); require(superAdmin != signer, "Super admin cannot remove themselves"); require(superAdminCount > 1, "Cannot remove the last super admin"); superAdmins[superAdmin] = false; superAdminCount--; emit SuperAdminRemoved(superAdmin, signer); } function transferSuperAdmin( address newSuperAdmin, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(newSuperAdmin, timestamp), signature, Role.SuperAdmin ); require( superAdmins[signer], "Only super admin can transfer their rights" ); require( !superAdmins[newSuperAdmin], "Address is already a super admin" ); superAdmins[signer] = false; superAdmins[newSuperAdmin] = true; if (!admins[newSuperAdmin]) { admins[newSuperAdmin] = true; emit AdminAdded(newSuperAdmin, signer); } emit SuperAdminRemoved(signer, signer); emit SuperAdminAdded(newSuperAdmin, signer); } function setMaxSuperAdmins( uint256 newMaxSuperAdmins, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(newMaxSuperAdmins, timestamp), signature, Role.SuperAdmin ); require( newMaxSuperAdmins >= superAdminCount, "New max must be greater than or equal to current count" ); maxSuperAdmins = newMaxSuperAdmins; emit MaxSuperAdminsUpdated(newMaxSuperAdmins, signer); } function addAdmin( address newAdmin, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(newAdmin, timestamp), signature, Role.SuperAdmin ); require(!admins[newAdmin], "Address is already an admin"); admins[newAdmin] = true; emit AdminAdded(newAdmin, signer); } function removeAdmin( address admin, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(admin, timestamp), signature, Role.SuperAdmin ); require(admins[admin], "Address is not an admin"); admins[admin] = false; emit AdminRemoved(admin, signer); } function setMulticallContract( address _multicallContract, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(_multicallContract, timestamp), signature, Role.SuperAdmin ); multicallContract = _multicallContract; emit MulticallContractUpdated(_multicallContract, signer); } function banUser( address user, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(user, timestamp), signature, Role.Admin ); bannedUsers[user] = true; emit UserBanned(user, signer); } function unbanUser( address user, uint256 timestamp, bytes memory signature ) external { address signer = verifySignature( abi.encodePacked(user, timestamp), signature, Role.Admin ); bannedUsers[user] = false; emit UserUnbanned(user, signer); } function supportsInterface( bytes4 interfaceId ) public view virtual override(ERC1155Upgradeable) returns (bool) { return super.supportsInterface(interfaceId); } function verifySignature( bytes memory data, bytes memory signature, Role requiredRole ) internal returns (address) { bytes32 hash = keccak256(abi.encodePacked(data, SELF_ADDRESS)); bytes32 signatureHash = keccak256(abi.encodePacked(hash, signature)); require(!usedSignatures[signatureHash], "Signature already used"); usedSignatures[signatureHash] = true; address signer = hash.toEthSignedMessageHash().recover(signature); if (requiredRole == Role.SuperAdmin) { require(superAdmins[signer], "Signer is not a super admin"); } else if (requiredRole == Role.Admin) { require( admins[signer] || superAdmins[signer], "Signer is not an admin" ); } else if (requiredRole == Role.ContractAdmin) { require(signer == contractAdmin, "Signer is not the deployer"); } else { revert("Invalid role"); } return signer; } function _authorizeUpgrade(address newImplementation) internal override {} }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract ABI
API[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"signer","type":"address"}],"name":"AdminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":true,"internalType":"address","name":"signer","type":"address"}],"name":"AdminRemoved","type":"event"},{"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":"oldContractAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newContractAdmin","type":"address"}],"name":"ContractAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"},{"indexed":false,"internalType":"address","name":"executor","type":"address"}],"name":"ContractUpgradeAuthorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxSuperAdmins","type":"uint256"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"MaxSuperAdminsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newMulticallContract","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"MulticallContractUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"NFTBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"NFTForceTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"tokenURI","type":"string"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"NFTMetadataUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"NFTMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newSuperAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"signer","type":"address"}],"name":"SuperAdminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"superAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"signer","type":"address"}],"name":"SuperAdminRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"signer","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"tokenURI","type":"string"}],"name":"TokenRegistered","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":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"signer","type":"address"}],"name":"UserBanned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"signer","type":"address"}],"name":"UserUnbanned","type":"event"},{"inputs":[],"name":"SELF_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSuperAdmin","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"addSuperAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"admins","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"banUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bannedUsers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"burnNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"forceTransferNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_multicallContract","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSuperAdmins","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mintNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"multicallContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"tokenURI","type":"string"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"registerNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"superAdmin","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"removeSuperAdmin","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":"newMaxSuperAdmins","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"setMaxSuperAdmins","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_multicallContract","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"setMulticallContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"newuri","type":"string"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"setURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"superAdminCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"superAdmins","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newContractAdmin","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"transferContractAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSuperAdmin","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"transferSuperAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"unbanUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"upgradeContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"usedSignatures","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523060805234801561001457600080fd5b50608051613eab61003e6000396000818161256f0152818161259801526126db0152613eab6000f3fe60806040526004361061025a5760003560e01c806368e01cfd11610144578063ad3cb1cc116100b6578063e985e9c51161007a578063e985e9c5146107c3578063ecce93c8146107e3578063f242432a14610803578063f69263fc14610823578063f978fd6114610843578063fb9171331461087357600080fd5b8063ad3cb1cc146106e6578063ae778ab814610717578063bd85b03914610737578063be4d4e7a14610783578063dcf069a0146107a357600080fd5b80638da3f257116101085780638da3f2571461062157806391d68fe01461064157806395d89b41146106615780639d8ede2e14610676578063a22cb46514610696578063ad25cb42146106b657600080fd5b806368e01cfd1461057b5780636df132821461059b57806377955245146105b15780637eb787f6146105d15780638988d078146105f157600080fd5b80632eb2c2d6116101dd5780634b641181116101a15780634b641181146104985780634e1273f4146104b85780634f1ef286146104e55780634f558e79146104f857806352d1902d146105465780635b5c9abf1461055b57600080fd5b80632eb2c2d6146103d057806333486c7a146103f05780633a07b5dc146104105780634170ec5114610448578063429b62e51461046857600080fd5b8063090c524611610224578063090c5246146103265780630e89341c14610346578063131769fc14610366578063160992da1461038657806318160ddd1461039c57600080fd5b8062923f9e1461025f578062fdd58e1461029457806301ffc9a7146102c257806306fdde03146102e2578063077f224a14610304575b600080fd5b34801561026b57600080fd5b5061027f61027a36600461332d565b610893565b60405190151581526020015b60405180910390f35b3480156102a057600080fd5b506102b46102af366004613362565b6108b9565b60405190815260200161028b565b3480156102ce57600080fd5b5061027f6102dd3660046133a2565b6108f0565b3480156102ee57600080fd5b506102f76108fb565b60405161028b919061340f565b34801561031057600080fd5b5061032461031f3660046134d7565b610989565b005b34801561033257600080fd5b5061032461034136600461354a565b610a9c565b34801561035257600080fd5b506102f761036136600461332d565b610b2e565b34801561037257600080fd5b506102b46103813660046135a0565b610c41565b34801561039257600080fd5b506102b460065481565b3480156103a857600080fd5b507f4a593662ee04d27b6a00ebb31be7fe0c102c2ade82a7c5d764f2df05dc4e2801546102b4565b3480156103dc57600080fd5b506103246103eb3660046136a8565b610d81565b3480156103fc57600080fd5b5061032461040b36600461354a565b610de8565b34801561041c57600080fd5b50600454610430906001600160a01b031681565b6040516001600160a01b03909116815260200161028b565b34801561045457600080fd5b5061032461046336600461354a565b610ec0565b34801561047457600080fd5b5061027f610483366004613751565b60096020526000908152604090205460ff1681565b3480156104a457600080fd5b506102b46104b336600461376c565b611103565b3480156104c457600080fd5b506104d86104d33660046137c0565b6112aa565b60405161028b91906138bb565b6103246104f33660046138ce565b611376565b34801561050457600080fd5b5061027f61051336600461332d565b60009081527f4a593662ee04d27b6a00ebb31be7fe0c102c2ade82a7c5d764f2df05dc4e28006020526040902054151590565b34801561055257600080fd5b506102b461138c565b34801561056757600080fd5b5061032461057636600461376c565b6113a9565b34801561058757600080fd5b50610324610596366004613911565b611495565b3480156105a757600080fd5b506102b460055481565b3480156105bd57600080fd5b50600354610430906001600160a01b031681565b3480156105dd57600080fd5b506103246105ec36600461354a565b61156c565b3480156105fd57600080fd5b5061027f61060c366004613751565b60076020526000908152604090205460ff1681565b34801561062d57600080fd5b5061032461063c36600461394a565b6115f3565b34801561064d57600080fd5b5061032461065c36600461354a565b61174b565b34801561066d57600080fd5b506102f7611834565b34801561068257600080fd5b5061032461069136600461354a565b611841565b3480156106a257600080fd5b506103246106b13660046139e0565b611915565b3480156106c257600080fd5b5061027f6106d1366004613751565b60086020526000908152604090205460ff1681565b3480156106f257600080fd5b506102f7604051806040016040528060058152602001640352e302e360dc1b81525081565b34801561072357600080fd5b5061032461073236600461354a565b611920565b34801561074357600080fd5b506102b461075236600461332d565b60009081527f4a593662ee04d27b6a00ebb31be7fe0c102c2ade82a7c5d764f2df05dc4e2800602052604090205490565b34801561078f57600080fd5b50600254610430906001600160a01b031681565b3480156107af57600080fd5b506103246107be36600461354a565b611ae6565b3480156107cf57600080fd5b5061027f6107de366004613a1c565b611b53565b3480156107ef57600080fd5b506103246107fe36600461354a565b611ba0565b34801561080f57600080fd5b5061032461081e366004613a4f565b611db1565b34801561082f57600080fd5b5061032461083e3660046135a0565b611e10565b34801561084f57600080fd5b5061027f61085e36600461332d565b600a6020526000908152604090205460ff1681565b34801561087f57600080fd5b5061032461088e36600461354a565b611f49565b6000818152600b6020526040812080548291906108af90613ab3565b9050119050919050565b6000818152600080516020613e56833981519152602090815260408083206001600160a01b03861684529091529020545b92915050565b60006108ea82611fe5565b6000805461090890613ab3565b80601f016020809104026020016040519081016040528092919081815260200182805461093490613ab3565b80156109815780601f1061095657610100808354040283529160200191610981565b820191906000526020600020905b81548152906001019060200180831161096457829003601f168201915b505050505081565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03166000811580156109ce5750825b90506000826001600160401b031660011480156109ea5750303b155b9050811580156109f8575080155b15610a165760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610a4057845460ff60401b1916600160401b1785555b610a4b888888612035565b8315610a9257845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2906020015b60405180910390a15b5050505050505050565b6000610acb8484604051602001610ab4929190613aed565b6040516020818303038152906040528360006121b0565b600480546001600160a01b0319166001600160a01b038781169182179092556040805191825291831660208201529192507f749fd2b8a141c6e6bbadd89bc4c73dd5602d57c519077d76885c2925b618754d91015b60405180910390a150505050565b6060610b3982610893565b610ba35760405162461bcd60e51b815260206004820152603060248201527f455243313135354d657461646174613a2055524920717565727920666f72206e60448201526f37b732bc34b9ba32b73a103a37b5b2b760811b60648201526084015b60405180910390fd5b6000828152600b602052604090208054610bbc90613ab3565b80601f0160208091040260200160405190810160405280929190818152602001828054610be890613ab3565b8015610c355780601f10610c0a57610100808354040283529160200191610c35565b820191906000526020600020905b815481529060010190602001808311610c1857829003601f168201915b50505050509050919050565b600080610c73868686604051602001610c5c93929190613b0a565b6040516020818303038152906040528460016121b0565b90506000855111610cc65760405162461bcd60e51b815260206004820152601960248201527f546f6b656e205552492063616e6e6f7420626520656d707479000000000000006044820152606401610b9a565b610ccf86610893565b15610d1c5760405162461bcd60e51b815260206004820152601760248201527f546f6b656e20494420616c7265616479206578697374730000000000000000006044820152606401610b9a565b6000868152600b60205260409020610d348682613b7f565b5085816001600160a01b03167f4b5bc7591644d2f3299bdf9f1a7bd1d878d8b52bfcf440710f621700142b001287604051610d6f919061340f565b60405180910390a35093949350505050565b336001600160a01b0386168114801590610da25750610da08682611b53565b155b15610dd35760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610b9a565b610de086868686866124a0565b505050505050565b6000610e008484604051602001610ab4929190613aed565b6001600160a01b03851660009081526009602052604090205490915060ff1615610e6c5760405162461bcd60e51b815260206004820152601b60248201527f4164647265737320697320616c726561647920616e2061646d696e00000000006044820152606401610b9a565b6001600160a01b03808516600081815260096020526040808220805460ff1916600117905551928416927fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b9190a350505050565b6000600554600003610f4c576003546001600160a01b03163314610f3a5760405162461bcd60e51b815260206004820152602b60248201527f4f6e6c79206465706c6f7965722063616e20616464207468652066697273742060448201526a39bab832b91030b236b4b760a91b6064820152608401610b9a565b506003546001600160a01b0316610f65565b610f628484604051602001610ab4929190613aed565b90505b60065460055410610fc75760405162461bcd60e51b815260206004820152602660248201527f4d6178696d756d206e756d626572206f662073757065722061646d696e732072604482015265195858da195960d21b6064820152608401610b9a565b6001600160a01b03841660009081526008602052604090205460ff16156110305760405162461bcd60e51b815260206004820181905260248201527f4164647265737320697320616c726561647920612073757065722061646d696e6044820152606401610b9a565b6001600160a01b03841660009081526008602090815260408083208054600160ff19918216811790925560099093529083208054909216179055600580549161107883613c54565b9190505550806001600160a01b0316846001600160a01b03167ffe3429bbb3d2e9099497080fc2dbbcab8e933dfb3a8630eb4566a1e506fc14a460405160405180910390a3806001600160a01b0316846001600160a01b03167fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b60405160405180910390a350505050565b6040516001600160601b0319606086901b1660208201526034810184905260548101839052600090819061113990607401610c5c565b6001600160a01b03871660009081526007602052604090205490915060ff16156111985760405162461bcd60e51b815260206004820152601060248201526f149958da5c1a595b9d0818985b9b995960821b6044820152606401610b9a565b6111a185610893565b6111e45760405162461bcd60e51b8152602060048201526014602482015273151bdad95b881b9bdd081c9959da5cdd195c995960621b6044820152606401610b9a565b6111ee86866108b9565b1561123b5760405162461bcd60e51b815260206004820152601c60248201527f5573657220616c7265616479206f776e73207468697320746f6b656e000000006044820152606401610b9a565b6112578686600160405180602001604052806000815250612507565b60408051600181526001600160a01b0383811660208301528792908916917f1ca97e6a4719f2f5f18859f14d7639ae913e62e8b761100b8b90e3f83cf56b19910160405180910390a35092949350505050565b606081518351146112db5781518351604051635b05999160e01b815260048101929092526024820152604401610b9a565b600083516001600160401b038111156112f6576112f6613422565b60405190808252806020026020018201604052801561131f578160200160208202803683370190505b50905060005b845181101561136e57602080820286010151611349906020808402870101516108b9565b82828151811061135b5761135b613c6d565b6020908102919091010152600101611325565b509392505050565b61137e612564565b611388828261260e565b5050565b60006113966126d0565b50600080516020613e3683398151915290565b6040516001600160601b0319606086901b16602082015260348101849052605481018390526000906113dd90607401610ab4565b905060016113eb86866108b9565b10156114395760405162461bcd60e51b815260206004820152601f60248201527f546f6b656e206e6f74206f776e65642062792066726f6d2061646472657373006044820152606401610b9a565b61144585856001612719565b60408051600181526001600160a01b0383811660208301528692908816917fd075f64b12bfbbce941c43210672ccee20a4440724d632d0ca9aac914f802a88910160405180910390a35050505050565b60006114b68484604051602001610ab4929190918252602082015260400190565b90506005548410156115295760405162461bcd60e51b815260206004820152603660248201527f4e6577206d6178206d7573742062652067726561746572207468616e206f7220604482015275195c5d585b081d1bc818dd5c9c995b9d0818dbdd5b9d60521b6064820152608401610b9a565b6006849055604080518581526001600160a01b03831660208201527f2688e006cf904d5be599056d1e7267e5bbb315cf48b35d4b5c788ec9967de7919101610b20565b600061159b8484604051602001611584929190613aed565b6040516020818303038152906040528360016121b0565b6001600160a01b03808616600081815260076020526040808220805460ff19166001179055519394509184169290917f9d2a81710659dec84d416abd31e959762fb5b9b3a09a6e0c505acccdde512c3591a350505050565b6040516001600160601b0319606088811b8216602084015287901b166034820152604881018590526068810183905260009061163190608801610ab4565b9050600161163f88876108b9565b101561168d5760405162461bcd60e51b815260206004820152601f60248201527f546f6b656e206e6f74206f776e65642062792066726f6d2061646472657373006044820152606401610b9a565b61169786866108b9565b156116ee5760405162461bcd60e51b815260206004820152602160248201527f526563697069656e7420616c7265616479206f776e73207468697320746f6b656044820152603760f91b6064820152608401610b9a565b6116fc878787600188612781565b6040516001600160a01b0382811682528691818916918a16907f78f3c3bddc03f572d28e527de0ae720553c087e1cda520b45f98f766ca250a4b9060200160405180910390a450505050505050565b6001600160a01b0383166117b25760405162461bcd60e51b815260206004820152602860248201527f4e657720636f6e747261637441646d696e2063616e6e6f74206265207a65726f604482015267206164647265737360c01b6064820152608401610b9a565b6117df83836040516020016117c8929190613aed565b6040516020818303038152906040528260026121b0565b50600380546001600160a01b038581166001600160a01b0319831681179093556040519116919082907f2f4e7de2a1dbac81744f8c97250194a39d96545eb864d155412811ff2f9c9ff890600090a350505050565b6001805461090890613ab3565b60006118598484604051602001610ab4929190613aed565b6001600160a01b03851660009081526009602052604090205490915060ff166118c45760405162461bcd60e51b815260206004820152601760248201527f41646472657373206973206e6f7420616e2061646d696e0000000000000000006044820152606401610b9a565b6001600160a01b03808516600081815260096020526040808220805460ff1916905551928416927fdb9d5d31320daf5bc7181d565b6da4d12e30f0f4d5aa324a992426c14a1d19ce9190a350505050565b61138833838361280f565b60006119388484604051602001610ab4929190613aed565b6001600160a01b03851660009081526008602052604090205490915060ff166119a35760405162461bcd60e51b815260206004820152601c60248201527f41646472657373206973206e6f7420612073757065722061646d696e000000006044820152606401610b9a565b806001600160a01b0316846001600160a01b031603611a105760405162461bcd60e51b8152602060048201526024808201527f53757065722061646d696e2063616e6e6f742072656d6f7665207468656d73656044820152636c76657360e01b6064820152608401610b9a565b600160055411611a6d5760405162461bcd60e51b815260206004820152602260248201527f43616e6e6f742072656d6f766520746865206c6173742073757065722061646d60448201526134b760f11b6064820152608401610b9a565b6001600160a01b0384166000908152600860205260408120805460ff191690556005805491611a9b83613c83565b9190505550806001600160a01b0316846001600160a01b03167f14e801d698dd3baa14cf6bf5b3af3e5b6d4b02292ca476cdffd3bf8f77737a1a60405160405180910390a350505050565b6000611afe8484604051602001611584929190613aed565b6001600160a01b03808616600081815260076020526040808220805460ff19169055519394509184169290917ff11fd0be5eda892011eed5ccf21f149a3e3533001e220f8aef844d83842ac61991a350505050565b6001600160a01b0391821660009081527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c45016020908152604080832093909416825291909152205460ff1690565b6000611bb88484604051602001610ab4929190613aed565b6001600160a01b03811660009081526008602052604090205490915060ff16611c365760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c792073757065722061646d696e2063616e207472616e736665722074686044820152696569722072696768747360b01b6064820152608401610b9a565b6001600160a01b03841660009081526008602052604090205460ff1615611c9f5760405162461bcd60e51b815260206004820181905260248201527f4164647265737320697320616c726561647920612073757065722061646d696e6044820152606401610b9a565b6001600160a01b038082166000908152600860209081526040808320805460ff199081169091559388168352808320805490941660011790935560099052205460ff16611d35576001600160a01b03808516600081815260096020526040808220805460ff1916600117905551928416927fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b9190a35b6040516001600160a01b0382169081907f14e801d698dd3baa14cf6bf5b3af3e5b6d4b02292ca476cdffd3bf8f77737a1a90600090a3806001600160a01b0316846001600160a01b03167ffe3429bbb3d2e9099497080fc2dbbcab8e933dfb3a8630eb4566a1e506fc14a460405160405180910390a350505050565b336001600160a01b0386168114801590611dd25750611dd08682611b53565b155b15611e035760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610b9a565b610de08686868686612781565b611e3f848484604051602001611e2893929190613b0a565b6040516020818303038152906040528260016121b0565b506000835111611e875760405162461bcd60e51b81526020600482015260136024820152725552492063616e6e6f7420626520656d70747960681b6044820152606401610b9a565b611e9084610893565b611ef25760405162461bcd60e51b815260206004820152602d60248201527f455243313135354d657461646174613a2055524920736574206f66206e6f6e6560448201526c3c34b9ba32b73a103a37b5b2b760991b6064820152608401610b9a565b6000848152600b60205260409020611f0a8482613b7f565b50837f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b84604051611f3b919061340f565b60405180910390a250505050565b6000611f788484604051602001611f61929190613aed565b6040516020818303038152906040528360026121b0565b604080516001600160a01b03878116825283166020820152338183015290519192507f8b64c5fbfcf02e8cd60a3e3f6fed1999e52f31f3c6bc00215e4734ed681b6605919081900360600190a1604080516000815260208101909152611fdf908590611376565b50505050565b60006001600160e01b03198216636cdb3d1360e11b148061201657506001600160e01b031982166303a24d0760e21b145b806108ea57506301ffc9a760e01b6001600160e01b03198316146108ea565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b031660008115801561207a5750825b90506000826001600160401b031660011480156120965750303b155b9050811580156120a4575080155b156120c25760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156120ec57845460ff60401b1916600160401b1785555b612104604051806020016040528060008152506128b7565b61210c6128c8565b6121146128c8565b600280546001600160a01b03199081163017909155600380549091163317905560006121408982613b7f565b50600161214d8882613b7f565b50600480546001600160a01b0319166001600160a01b03881617905560026006558315610a9257845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602001610a89565b60025460405160009182916121d59187916001600160a01b0390911690602001613c9a565b60405160208183030381529060405280519060200120905060008185604051602001612202929190613ccc565b60408051601f1981840301815291815281516020928301206000818152600a90935291205490915060ff16156122735760405162461bcd60e51b815260206004820152601660248201527514da59db985d1d5c9948185b1c9958591e481d5cd95960521b6044820152606401610b9a565b6000818152600a60205260408120805460ff191660011790557f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c839052603c81206122c290876128d0565b905060008560028111156122d8576122d8613cf2565b0361234a576001600160a01b03811660009081526008602052604090205460ff166123455760405162461bcd60e51b815260206004820152601b60248201527f5369676e6572206973206e6f7420612073757065722061646d696e00000000006044820152606401610b9a565b612494565b600185600281111561235e5761235e613cf2565b036123e7576001600160a01b03811660009081526009602052604090205460ff16806123a257506001600160a01b03811660009081526008602052604090205460ff165b6123455760405162461bcd60e51b815260206004820152601660248201527529b4b3b732b91034b9903737ba1030b71030b236b4b760511b6044820152606401610b9a565b60028560028111156123fb576123fb613cf2565b0361245d576003546001600160a01b038281169116146123455760405162461bcd60e51b815260206004820152601a60248201527f5369676e6572206973206e6f7420746865206465706c6f7965720000000000006044820152606401610b9a565b60405162461bcd60e51b815260206004820152600c60248201526b496e76616c696420726f6c6560a01b6044820152606401610b9a565b925050505b9392505050565b6001600160a01b0384166124ca57604051632bfa23e760e11b815260006004820152602401610b9a565b6001600160a01b0385166124f357604051626a0d4560e21b815260006004820152602401610b9a565b61250085858585856128fa565b5050505050565b6001600160a01b03841661253157604051632bfa23e760e11b815260006004820152602401610b9a565b60408051600180825260208201869052818301908152606082018590526080820190925290610de06000878484876128fa565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806125eb57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166125df600080516020613e36833981519152546001600160a01b031690565b6001600160a01b031614155b156126095760405163703e46dd60e11b815260040160405180910390fd5b565b50565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612668575060408051601f3d908101601f1916820190925261266591810190613d08565b60015b61269057604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610b9a565b600080516020613e3683398151915281146126c157604051632a87526960e21b815260048101829052602401610b9a565b6126cb838361294d565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146126095760405163703e46dd60e11b815260040160405180910390fd5b6001600160a01b03831661274257604051626a0d4560e21b815260006004820152602401610b9a565b604080516001808252602082018590528183019081526060820184905260a08201909252600060808201818152919291612500918791859085906128fa565b6001600160a01b0384166127ab57604051632bfa23e760e11b815260006004820152602401610b9a565b6001600160a01b0385166127d457604051626a0d4560e21b815260006004820152602401610b9a565b6040805160018082526020820186905281830190815260608201859052608082019092529061280687878484876128fa565b50505050505050565b600080516020613e568339815191526001600160a01b0383166128475760405162ced3e160e81b815260006004820152602401610b9a565b6001600160a01b038481166000818152600184016020908152604080832094881680845294825291829020805460ff191687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b6128bf6129a3565b61260b816129ec565b6126096129a3565b6000806000806128e086866129fd565b9250925092506128f08282612a4a565b5090949350505050565b61290685858585612b03565b6001600160a01b03841615612500578251339060010361293f5760208481015190840151612938838989858589612c73565b5050610de0565b610de0818787878787612d97565b61295682612e80565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511561299b576126cb8282612ee5565b611388612f5b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661260957604051631afcd79f60e31b815260040160405180910390fd5b6129f46129a3565b61260b81612f7a565b60008060008351604103612a375760208401516040850151606086015160001a612a2988828585612fb4565b955095509550505050612a43565b50508151600091506002905b9250925092565b6000826003811115612a5e57612a5e613cf2565b03612a67575050565b6001826003811115612a7b57612a7b613cf2565b03612a995760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115612aad57612aad613cf2565b03612ace5760405163fce698f760e01b815260048101829052602401610b9a565b6003826003811115612ae257612ae2613cf2565b03611388576040516335e2f38360e21b815260048101829052602401610b9a565b7f4a593662ee04d27b6a00ebb31be7fe0c102c2ade82a7c5d764f2df05dc4e2800612b3085858585613083565b6001600160a01b038516612bde576000805b8451811015612bc2576000848281518110612b5f57612b5f613c6d565b6020026020010151905080846000016000888581518110612b8257612b82613c6d565b602002602001015181526020019081526020016000206000828254612ba79190613d21565b90915550612bb790508184613d21565b925050600101612b42565b5080826001016000828254612bd79190613d21565b9091555050505b6001600160a01b038416612500576000805b8451811015612c5f576000848281518110612c0d57612c0d613c6d565b6020026020010151905080846000016000888581518110612c3057612c30613c6d565b602090810291909101810151825281019190915260400160002080549190910390559190910190600101612bf0565b506001820180549190910390555050505050565b6001600160a01b0384163b15610de05760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190612cb79089908990889088908890600401613d34565b6020604051808303816000875af1925050508015612cf2575060408051601f3d908101601f19168201909252612cef91810190613d79565b60015b612d5b573d808015612d20576040519150601f19603f3d011682016040523d82523d6000602084013e612d25565b606091505b508051600003612d5357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b9a565b805181602001fd5b6001600160e01b0319811663f23a6e6160e01b1461280657604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b9a565b6001600160a01b0384163b15610de05760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190612ddb9089908990889088908890600401613d96565b6020604051808303816000875af1925050508015612e16575060408051601f3d908101601f19168201909252612e1391810190613d79565b60015b612e44573d808015612d20576040519150601f19603f3d011682016040523d82523d6000602084013e612d25565b6001600160e01b0319811663bc197c8160e01b1461280657604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b9a565b806001600160a01b03163b600003612eb657604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610b9a565b600080516020613e3683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051612f029190613df4565b600060405180830381855af49150503d8060008114612f3d576040519150601f19603f3d011682016040523d82523d6000602084013e612f42565b606091505b5091509150612f528583836132a8565b95945050505050565b34156126095760405163b398979f60e01b815260040160405180910390fd5b600080516020613e568339815191527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c45026126cb8382613b7f565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115612fef5750600091506003905082613079565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015613043573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661306f57506000925060019150829050613079565b9250600091508190505b9450945094915050565b80518251600080516020613e5683398151915291146130c25782518251604051635b05999160e01b815260048101929092526024820152604401610b9a565b3360005b84518110156131c8576020818102868101820151908601909101516001600160a01b03891615613179576000828152602086815260408083206001600160a01b038d16845290915290205481811015613152576040516303dee4c560e01b81526001600160a01b038b166004820152602481018290526044810183905260648101849052608401610b9a565b6000838152602087815260408083206001600160a01b038e16845290915290209082900390555b6001600160a01b038816156131be576000828152602086815260408083206001600160a01b038c168452909152812080548392906131b8908490613d21565b90915550505b50506001016130c6565b5083516001036132495760208401516000906020850151909150866001600160a01b0316886001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62858560405161323a929190918252602082015260400190565b60405180910390a45050610de0565b846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051613298929190613e10565b60405180910390a4505050505050565b6060826132bd576132b882613304565b612499565b81511580156132d457506001600160a01b0384163b155b156132fd57604051639996b31560e01b81526001600160a01b0385166004820152602401610b9a565b5080612499565b8051156133145780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60006020828403121561333f57600080fd5b5035919050565b80356001600160a01b038116811461335d57600080fd5b919050565b6000806040838503121561337557600080fd5b61337e83613346565b946020939093013593505050565b6001600160e01b03198116811461260b57600080fd5b6000602082840312156133b457600080fd5b81356124998161338c565b60005b838110156133da5781810151838201526020016133c2565b50506000910152565b600081518084526133fb8160208601602086016133bf565b601f01601f19169290920160200192915050565b60208152600061249960208301846133e3565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561346057613460613422565b604052919050565b600082601f83011261347957600080fd5b81356001600160401b0381111561349257613492613422565b6134a5601f8201601f1916602001613438565b8181528460208386010111156134ba57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000606084860312156134ec57600080fd5b83356001600160401b038082111561350357600080fd5b61350f87838801613468565b9450602086013591508082111561352557600080fd5b5061353286828701613468565b92505061354160408501613346565b90509250925092565b60008060006060848603121561355f57600080fd5b61356884613346565b92506020840135915060408401356001600160401b0381111561358a57600080fd5b61359686828701613468565b9150509250925092565b600080600080608085870312156135b657600080fd5b8435935060208501356001600160401b03808211156135d457600080fd5b6135e088838901613468565b94506040870135935060608701359150808211156135fd57600080fd5b5061360a87828801613468565b91505092959194509250565b60006001600160401b0382111561362f5761362f613422565b5060051b60200190565b600082601f83011261364a57600080fd5b8135602061365f61365a83613616565b613438565b8083825260208201915060208460051b87010193508684111561368157600080fd5b602086015b8481101561369d5780358352918301918301613686565b509695505050505050565b600080600080600060a086880312156136c057600080fd5b6136c986613346565b94506136d760208701613346565b935060408601356001600160401b03808211156136f357600080fd5b6136ff89838a01613639565b9450606088013591508082111561371557600080fd5b61372189838a01613639565b9350608088013591508082111561373757600080fd5b5061374488828901613468565b9150509295509295909350565b60006020828403121561376357600080fd5b61249982613346565b6000806000806080858703121561378257600080fd5b61378b85613346565b9350602085013592506040850135915060608501356001600160401b038111156137b457600080fd5b61360a87828801613468565b600080604083850312156137d357600080fd5b82356001600160401b03808211156137ea57600080fd5b818501915085601f8301126137fe57600080fd5b8135602061380e61365a83613616565b82815260059290921b8401810191818101908984111561382d57600080fd5b948201945b838610156138525761384386613346565b82529482019490820190613832565b9650508601359250508082111561386857600080fd5b5061387585828601613639565b9150509250929050565b60008151808452602080850194506020840160005b838110156138b057815187529582019590820190600101613894565b509495945050505050565b602081526000612499602083018461387f565b600080604083850312156138e157600080fd5b6138ea83613346565b915060208301356001600160401b0381111561390557600080fd5b61387585828601613468565b60008060006060848603121561392657600080fd5b833592506020840135915060408401356001600160401b0381111561358a57600080fd5b60008060008060008060c0878903121561396357600080fd5b61396c87613346565b955061397a60208801613346565b94506040870135935060608701356001600160401b038082111561399d57600080fd5b6139a98a838b01613468565b94506080890135935060a08901359150808211156139c657600080fd5b506139d389828a01613468565b9150509295509295509295565b600080604083850312156139f357600080fd5b6139fc83613346565b915060208301358015158114613a1157600080fd5b809150509250929050565b60008060408385031215613a2f57600080fd5b613a3883613346565b9150613a4660208401613346565b90509250929050565b600080600080600060a08688031215613a6757600080fd5b613a7086613346565b9450613a7e60208701613346565b9350604086013592506060860135915060808601356001600160401b03811115613aa757600080fd5b61374488828901613468565b600181811c90821680613ac757607f821691505b602082108103613ae757634e487b7160e01b600052602260045260246000fd5b50919050565b60609290921b6001600160601b0319168252601482015260340190565b83815260008351613b228160208501602088016133bf565b60209201918201929092526040019392505050565b601f8211156126cb576000816000526020600020601f850160051c81016020861015613b605750805b601f850160051c820191505b81811015610de057828155600101613b6c565b81516001600160401b03811115613b9857613b98613422565b613bac81613ba68454613ab3565b84613b37565b602080601f831160018114613be15760008415613bc95750858301515b600019600386901b1c1916600185901b178555610de0565b600085815260208120601f198616915b82811015613c1057888601518255948401946001909101908401613bf1565b5085821015613c2e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600060018201613c6657613c66613c3e565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600081613c9257613c92613c3e565b506000190190565b60008351613cac8184602088016133bf565b60609390931b6001600160601b0319169190920190815260140192915050565b82815260008251613ce48160208501602087016133bf565b919091016020019392505050565b634e487b7160e01b600052602160045260246000fd5b600060208284031215613d1a57600080fd5b5051919050565b808201808211156108ea576108ea613c3e565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090613d6e908301846133e3565b979650505050505050565b600060208284031215613d8b57600080fd5b81516124998161338c565b6001600160a01b0386811682528516602082015260a060408201819052600090613dc29083018661387f565b8281036060840152613dd4818661387f565b90508281036080840152613de881856133e3565b98975050505050505050565b60008251613e068184602087016133bf565b9190910192915050565b604081526000613e23604083018561387f565b8281036020840152612f52818561387f56fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4500a26469706673582212203beae7fa062124a2dd7cd0358c764b01133cb071250938b5375769a11b7b88ce64736f6c63430008180033
Deployed Bytecode
0x60806040526004361061025a5760003560e01c806368e01cfd11610144578063ad3cb1cc116100b6578063e985e9c51161007a578063e985e9c5146107c3578063ecce93c8146107e3578063f242432a14610803578063f69263fc14610823578063f978fd6114610843578063fb9171331461087357600080fd5b8063ad3cb1cc146106e6578063ae778ab814610717578063bd85b03914610737578063be4d4e7a14610783578063dcf069a0146107a357600080fd5b80638da3f257116101085780638da3f2571461062157806391d68fe01461064157806395d89b41146106615780639d8ede2e14610676578063a22cb46514610696578063ad25cb42146106b657600080fd5b806368e01cfd1461057b5780636df132821461059b57806377955245146105b15780637eb787f6146105d15780638988d078146105f157600080fd5b80632eb2c2d6116101dd5780634b641181116101a15780634b641181146104985780634e1273f4146104b85780634f1ef286146104e55780634f558e79146104f857806352d1902d146105465780635b5c9abf1461055b57600080fd5b80632eb2c2d6146103d057806333486c7a146103f05780633a07b5dc146104105780634170ec5114610448578063429b62e51461046857600080fd5b8063090c524611610224578063090c5246146103265780630e89341c14610346578063131769fc14610366578063160992da1461038657806318160ddd1461039c57600080fd5b8062923f9e1461025f578062fdd58e1461029457806301ffc9a7146102c257806306fdde03146102e2578063077f224a14610304575b600080fd5b34801561026b57600080fd5b5061027f61027a36600461332d565b610893565b60405190151581526020015b60405180910390f35b3480156102a057600080fd5b506102b46102af366004613362565b6108b9565b60405190815260200161028b565b3480156102ce57600080fd5b5061027f6102dd3660046133a2565b6108f0565b3480156102ee57600080fd5b506102f76108fb565b60405161028b919061340f565b34801561031057600080fd5b5061032461031f3660046134d7565b610989565b005b34801561033257600080fd5b5061032461034136600461354a565b610a9c565b34801561035257600080fd5b506102f761036136600461332d565b610b2e565b34801561037257600080fd5b506102b46103813660046135a0565b610c41565b34801561039257600080fd5b506102b460065481565b3480156103a857600080fd5b507f4a593662ee04d27b6a00ebb31be7fe0c102c2ade82a7c5d764f2df05dc4e2801546102b4565b3480156103dc57600080fd5b506103246103eb3660046136a8565b610d81565b3480156103fc57600080fd5b5061032461040b36600461354a565b610de8565b34801561041c57600080fd5b50600454610430906001600160a01b031681565b6040516001600160a01b03909116815260200161028b565b34801561045457600080fd5b5061032461046336600461354a565b610ec0565b34801561047457600080fd5b5061027f610483366004613751565b60096020526000908152604090205460ff1681565b3480156104a457600080fd5b506102b46104b336600461376c565b611103565b3480156104c457600080fd5b506104d86104d33660046137c0565b6112aa565b60405161028b91906138bb565b6103246104f33660046138ce565b611376565b34801561050457600080fd5b5061027f61051336600461332d565b60009081527f4a593662ee04d27b6a00ebb31be7fe0c102c2ade82a7c5d764f2df05dc4e28006020526040902054151590565b34801561055257600080fd5b506102b461138c565b34801561056757600080fd5b5061032461057636600461376c565b6113a9565b34801561058757600080fd5b50610324610596366004613911565b611495565b3480156105a757600080fd5b506102b460055481565b3480156105bd57600080fd5b50600354610430906001600160a01b031681565b3480156105dd57600080fd5b506103246105ec36600461354a565b61156c565b3480156105fd57600080fd5b5061027f61060c366004613751565b60076020526000908152604090205460ff1681565b34801561062d57600080fd5b5061032461063c36600461394a565b6115f3565b34801561064d57600080fd5b5061032461065c36600461354a565b61174b565b34801561066d57600080fd5b506102f7611834565b34801561068257600080fd5b5061032461069136600461354a565b611841565b3480156106a257600080fd5b506103246106b13660046139e0565b611915565b3480156106c257600080fd5b5061027f6106d1366004613751565b60086020526000908152604090205460ff1681565b3480156106f257600080fd5b506102f7604051806040016040528060058152602001640352e302e360dc1b81525081565b34801561072357600080fd5b5061032461073236600461354a565b611920565b34801561074357600080fd5b506102b461075236600461332d565b60009081527f4a593662ee04d27b6a00ebb31be7fe0c102c2ade82a7c5d764f2df05dc4e2800602052604090205490565b34801561078f57600080fd5b50600254610430906001600160a01b031681565b3480156107af57600080fd5b506103246107be36600461354a565b611ae6565b3480156107cf57600080fd5b5061027f6107de366004613a1c565b611b53565b3480156107ef57600080fd5b506103246107fe36600461354a565b611ba0565b34801561080f57600080fd5b5061032461081e366004613a4f565b611db1565b34801561082f57600080fd5b5061032461083e3660046135a0565b611e10565b34801561084f57600080fd5b5061027f61085e36600461332d565b600a6020526000908152604090205460ff1681565b34801561087f57600080fd5b5061032461088e36600461354a565b611f49565b6000818152600b6020526040812080548291906108af90613ab3565b9050119050919050565b6000818152600080516020613e56833981519152602090815260408083206001600160a01b03861684529091529020545b92915050565b60006108ea82611fe5565b6000805461090890613ab3565b80601f016020809104026020016040519081016040528092919081815260200182805461093490613ab3565b80156109815780601f1061095657610100808354040283529160200191610981565b820191906000526020600020905b81548152906001019060200180831161096457829003601f168201915b505050505081565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03166000811580156109ce5750825b90506000826001600160401b031660011480156109ea5750303b155b9050811580156109f8575080155b15610a165760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610a4057845460ff60401b1916600160401b1785555b610a4b888888612035565b8315610a9257845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2906020015b60405180910390a15b5050505050505050565b6000610acb8484604051602001610ab4929190613aed565b6040516020818303038152906040528360006121b0565b600480546001600160a01b0319166001600160a01b038781169182179092556040805191825291831660208201529192507f749fd2b8a141c6e6bbadd89bc4c73dd5602d57c519077d76885c2925b618754d91015b60405180910390a150505050565b6060610b3982610893565b610ba35760405162461bcd60e51b815260206004820152603060248201527f455243313135354d657461646174613a2055524920717565727920666f72206e60448201526f37b732bc34b9ba32b73a103a37b5b2b760811b60648201526084015b60405180910390fd5b6000828152600b602052604090208054610bbc90613ab3565b80601f0160208091040260200160405190810160405280929190818152602001828054610be890613ab3565b8015610c355780601f10610c0a57610100808354040283529160200191610c35565b820191906000526020600020905b815481529060010190602001808311610c1857829003601f168201915b50505050509050919050565b600080610c73868686604051602001610c5c93929190613b0a565b6040516020818303038152906040528460016121b0565b90506000855111610cc65760405162461bcd60e51b815260206004820152601960248201527f546f6b656e205552492063616e6e6f7420626520656d707479000000000000006044820152606401610b9a565b610ccf86610893565b15610d1c5760405162461bcd60e51b815260206004820152601760248201527f546f6b656e20494420616c7265616479206578697374730000000000000000006044820152606401610b9a565b6000868152600b60205260409020610d348682613b7f565b5085816001600160a01b03167f4b5bc7591644d2f3299bdf9f1a7bd1d878d8b52bfcf440710f621700142b001287604051610d6f919061340f565b60405180910390a35093949350505050565b336001600160a01b0386168114801590610da25750610da08682611b53565b155b15610dd35760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610b9a565b610de086868686866124a0565b505050505050565b6000610e008484604051602001610ab4929190613aed565b6001600160a01b03851660009081526009602052604090205490915060ff1615610e6c5760405162461bcd60e51b815260206004820152601b60248201527f4164647265737320697320616c726561647920616e2061646d696e00000000006044820152606401610b9a565b6001600160a01b03808516600081815260096020526040808220805460ff1916600117905551928416927fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b9190a350505050565b6000600554600003610f4c576003546001600160a01b03163314610f3a5760405162461bcd60e51b815260206004820152602b60248201527f4f6e6c79206465706c6f7965722063616e20616464207468652066697273742060448201526a39bab832b91030b236b4b760a91b6064820152608401610b9a565b506003546001600160a01b0316610f65565b610f628484604051602001610ab4929190613aed565b90505b60065460055410610fc75760405162461bcd60e51b815260206004820152602660248201527f4d6178696d756d206e756d626572206f662073757065722061646d696e732072604482015265195858da195960d21b6064820152608401610b9a565b6001600160a01b03841660009081526008602052604090205460ff16156110305760405162461bcd60e51b815260206004820181905260248201527f4164647265737320697320616c726561647920612073757065722061646d696e6044820152606401610b9a565b6001600160a01b03841660009081526008602090815260408083208054600160ff19918216811790925560099093529083208054909216179055600580549161107883613c54565b9190505550806001600160a01b0316846001600160a01b03167ffe3429bbb3d2e9099497080fc2dbbcab8e933dfb3a8630eb4566a1e506fc14a460405160405180910390a3806001600160a01b0316846001600160a01b03167fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b60405160405180910390a350505050565b6040516001600160601b0319606086901b1660208201526034810184905260548101839052600090819061113990607401610c5c565b6001600160a01b03871660009081526007602052604090205490915060ff16156111985760405162461bcd60e51b815260206004820152601060248201526f149958da5c1a595b9d0818985b9b995960821b6044820152606401610b9a565b6111a185610893565b6111e45760405162461bcd60e51b8152602060048201526014602482015273151bdad95b881b9bdd081c9959da5cdd195c995960621b6044820152606401610b9a565b6111ee86866108b9565b1561123b5760405162461bcd60e51b815260206004820152601c60248201527f5573657220616c7265616479206f776e73207468697320746f6b656e000000006044820152606401610b9a565b6112578686600160405180602001604052806000815250612507565b60408051600181526001600160a01b0383811660208301528792908916917f1ca97e6a4719f2f5f18859f14d7639ae913e62e8b761100b8b90e3f83cf56b19910160405180910390a35092949350505050565b606081518351146112db5781518351604051635b05999160e01b815260048101929092526024820152604401610b9a565b600083516001600160401b038111156112f6576112f6613422565b60405190808252806020026020018201604052801561131f578160200160208202803683370190505b50905060005b845181101561136e57602080820286010151611349906020808402870101516108b9565b82828151811061135b5761135b613c6d565b6020908102919091010152600101611325565b509392505050565b61137e612564565b611388828261260e565b5050565b60006113966126d0565b50600080516020613e3683398151915290565b6040516001600160601b0319606086901b16602082015260348101849052605481018390526000906113dd90607401610ab4565b905060016113eb86866108b9565b10156114395760405162461bcd60e51b815260206004820152601f60248201527f546f6b656e206e6f74206f776e65642062792066726f6d2061646472657373006044820152606401610b9a565b61144585856001612719565b60408051600181526001600160a01b0383811660208301528692908816917fd075f64b12bfbbce941c43210672ccee20a4440724d632d0ca9aac914f802a88910160405180910390a35050505050565b60006114b68484604051602001610ab4929190918252602082015260400190565b90506005548410156115295760405162461bcd60e51b815260206004820152603660248201527f4e6577206d6178206d7573742062652067726561746572207468616e206f7220604482015275195c5d585b081d1bc818dd5c9c995b9d0818dbdd5b9d60521b6064820152608401610b9a565b6006849055604080518581526001600160a01b03831660208201527f2688e006cf904d5be599056d1e7267e5bbb315cf48b35d4b5c788ec9967de7919101610b20565b600061159b8484604051602001611584929190613aed565b6040516020818303038152906040528360016121b0565b6001600160a01b03808616600081815260076020526040808220805460ff19166001179055519394509184169290917f9d2a81710659dec84d416abd31e959762fb5b9b3a09a6e0c505acccdde512c3591a350505050565b6040516001600160601b0319606088811b8216602084015287901b166034820152604881018590526068810183905260009061163190608801610ab4565b9050600161163f88876108b9565b101561168d5760405162461bcd60e51b815260206004820152601f60248201527f546f6b656e206e6f74206f776e65642062792066726f6d2061646472657373006044820152606401610b9a565b61169786866108b9565b156116ee5760405162461bcd60e51b815260206004820152602160248201527f526563697069656e7420616c7265616479206f776e73207468697320746f6b656044820152603760f91b6064820152608401610b9a565b6116fc878787600188612781565b6040516001600160a01b0382811682528691818916918a16907f78f3c3bddc03f572d28e527de0ae720553c087e1cda520b45f98f766ca250a4b9060200160405180910390a450505050505050565b6001600160a01b0383166117b25760405162461bcd60e51b815260206004820152602860248201527f4e657720636f6e747261637441646d696e2063616e6e6f74206265207a65726f604482015267206164647265737360c01b6064820152608401610b9a565b6117df83836040516020016117c8929190613aed565b6040516020818303038152906040528260026121b0565b50600380546001600160a01b038581166001600160a01b0319831681179093556040519116919082907f2f4e7de2a1dbac81744f8c97250194a39d96545eb864d155412811ff2f9c9ff890600090a350505050565b6001805461090890613ab3565b60006118598484604051602001610ab4929190613aed565b6001600160a01b03851660009081526009602052604090205490915060ff166118c45760405162461bcd60e51b815260206004820152601760248201527f41646472657373206973206e6f7420616e2061646d696e0000000000000000006044820152606401610b9a565b6001600160a01b03808516600081815260096020526040808220805460ff1916905551928416927fdb9d5d31320daf5bc7181d565b6da4d12e30f0f4d5aa324a992426c14a1d19ce9190a350505050565b61138833838361280f565b60006119388484604051602001610ab4929190613aed565b6001600160a01b03851660009081526008602052604090205490915060ff166119a35760405162461bcd60e51b815260206004820152601c60248201527f41646472657373206973206e6f7420612073757065722061646d696e000000006044820152606401610b9a565b806001600160a01b0316846001600160a01b031603611a105760405162461bcd60e51b8152602060048201526024808201527f53757065722061646d696e2063616e6e6f742072656d6f7665207468656d73656044820152636c76657360e01b6064820152608401610b9a565b600160055411611a6d5760405162461bcd60e51b815260206004820152602260248201527f43616e6e6f742072656d6f766520746865206c6173742073757065722061646d60448201526134b760f11b6064820152608401610b9a565b6001600160a01b0384166000908152600860205260408120805460ff191690556005805491611a9b83613c83565b9190505550806001600160a01b0316846001600160a01b03167f14e801d698dd3baa14cf6bf5b3af3e5b6d4b02292ca476cdffd3bf8f77737a1a60405160405180910390a350505050565b6000611afe8484604051602001611584929190613aed565b6001600160a01b03808616600081815260076020526040808220805460ff19169055519394509184169290917ff11fd0be5eda892011eed5ccf21f149a3e3533001e220f8aef844d83842ac61991a350505050565b6001600160a01b0391821660009081527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c45016020908152604080832093909416825291909152205460ff1690565b6000611bb88484604051602001610ab4929190613aed565b6001600160a01b03811660009081526008602052604090205490915060ff16611c365760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c792073757065722061646d696e2063616e207472616e736665722074686044820152696569722072696768747360b01b6064820152608401610b9a565b6001600160a01b03841660009081526008602052604090205460ff1615611c9f5760405162461bcd60e51b815260206004820181905260248201527f4164647265737320697320616c726561647920612073757065722061646d696e6044820152606401610b9a565b6001600160a01b038082166000908152600860209081526040808320805460ff199081169091559388168352808320805490941660011790935560099052205460ff16611d35576001600160a01b03808516600081815260096020526040808220805460ff1916600117905551928416927fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b9190a35b6040516001600160a01b0382169081907f14e801d698dd3baa14cf6bf5b3af3e5b6d4b02292ca476cdffd3bf8f77737a1a90600090a3806001600160a01b0316846001600160a01b03167ffe3429bbb3d2e9099497080fc2dbbcab8e933dfb3a8630eb4566a1e506fc14a460405160405180910390a350505050565b336001600160a01b0386168114801590611dd25750611dd08682611b53565b155b15611e035760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610b9a565b610de08686868686612781565b611e3f848484604051602001611e2893929190613b0a565b6040516020818303038152906040528260016121b0565b506000835111611e875760405162461bcd60e51b81526020600482015260136024820152725552492063616e6e6f7420626520656d70747960681b6044820152606401610b9a565b611e9084610893565b611ef25760405162461bcd60e51b815260206004820152602d60248201527f455243313135354d657461646174613a2055524920736574206f66206e6f6e6560448201526c3c34b9ba32b73a103a37b5b2b760991b6064820152608401610b9a565b6000848152600b60205260409020611f0a8482613b7f565b50837f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b84604051611f3b919061340f565b60405180910390a250505050565b6000611f788484604051602001611f61929190613aed565b6040516020818303038152906040528360026121b0565b604080516001600160a01b03878116825283166020820152338183015290519192507f8b64c5fbfcf02e8cd60a3e3f6fed1999e52f31f3c6bc00215e4734ed681b6605919081900360600190a1604080516000815260208101909152611fdf908590611376565b50505050565b60006001600160e01b03198216636cdb3d1360e11b148061201657506001600160e01b031982166303a24d0760e21b145b806108ea57506301ffc9a760e01b6001600160e01b03198316146108ea565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b031660008115801561207a5750825b90506000826001600160401b031660011480156120965750303b155b9050811580156120a4575080155b156120c25760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156120ec57845460ff60401b1916600160401b1785555b612104604051806020016040528060008152506128b7565b61210c6128c8565b6121146128c8565b600280546001600160a01b03199081163017909155600380549091163317905560006121408982613b7f565b50600161214d8882613b7f565b50600480546001600160a01b0319166001600160a01b03881617905560026006558315610a9257845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602001610a89565b60025460405160009182916121d59187916001600160a01b0390911690602001613c9a565b60405160208183030381529060405280519060200120905060008185604051602001612202929190613ccc565b60408051601f1981840301815291815281516020928301206000818152600a90935291205490915060ff16156122735760405162461bcd60e51b815260206004820152601660248201527514da59db985d1d5c9948185b1c9958591e481d5cd95960521b6044820152606401610b9a565b6000818152600a60205260408120805460ff191660011790557f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c839052603c81206122c290876128d0565b905060008560028111156122d8576122d8613cf2565b0361234a576001600160a01b03811660009081526008602052604090205460ff166123455760405162461bcd60e51b815260206004820152601b60248201527f5369676e6572206973206e6f7420612073757065722061646d696e00000000006044820152606401610b9a565b612494565b600185600281111561235e5761235e613cf2565b036123e7576001600160a01b03811660009081526009602052604090205460ff16806123a257506001600160a01b03811660009081526008602052604090205460ff165b6123455760405162461bcd60e51b815260206004820152601660248201527529b4b3b732b91034b9903737ba1030b71030b236b4b760511b6044820152606401610b9a565b60028560028111156123fb576123fb613cf2565b0361245d576003546001600160a01b038281169116146123455760405162461bcd60e51b815260206004820152601a60248201527f5369676e6572206973206e6f7420746865206465706c6f7965720000000000006044820152606401610b9a565b60405162461bcd60e51b815260206004820152600c60248201526b496e76616c696420726f6c6560a01b6044820152606401610b9a565b925050505b9392505050565b6001600160a01b0384166124ca57604051632bfa23e760e11b815260006004820152602401610b9a565b6001600160a01b0385166124f357604051626a0d4560e21b815260006004820152602401610b9a565b61250085858585856128fa565b5050505050565b6001600160a01b03841661253157604051632bfa23e760e11b815260006004820152602401610b9a565b60408051600180825260208201869052818301908152606082018590526080820190925290610de06000878484876128fa565b306001600160a01b037f0000000000000000000000000fdf059455ea4067b6f1bab18ee871ccd64c609c1614806125eb57507f0000000000000000000000000fdf059455ea4067b6f1bab18ee871ccd64c609c6001600160a01b03166125df600080516020613e36833981519152546001600160a01b031690565b6001600160a01b031614155b156126095760405163703e46dd60e11b815260040160405180910390fd5b565b50565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612668575060408051601f3d908101601f1916820190925261266591810190613d08565b60015b61269057604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610b9a565b600080516020613e3683398151915281146126c157604051632a87526960e21b815260048101829052602401610b9a565b6126cb838361294d565b505050565b306001600160a01b037f0000000000000000000000000fdf059455ea4067b6f1bab18ee871ccd64c609c16146126095760405163703e46dd60e11b815260040160405180910390fd5b6001600160a01b03831661274257604051626a0d4560e21b815260006004820152602401610b9a565b604080516001808252602082018590528183019081526060820184905260a08201909252600060808201818152919291612500918791859085906128fa565b6001600160a01b0384166127ab57604051632bfa23e760e11b815260006004820152602401610b9a565b6001600160a01b0385166127d457604051626a0d4560e21b815260006004820152602401610b9a565b6040805160018082526020820186905281830190815260608201859052608082019092529061280687878484876128fa565b50505050505050565b600080516020613e568339815191526001600160a01b0383166128475760405162ced3e160e81b815260006004820152602401610b9a565b6001600160a01b038481166000818152600184016020908152604080832094881680845294825291829020805460ff191687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b6128bf6129a3565b61260b816129ec565b6126096129a3565b6000806000806128e086866129fd565b9250925092506128f08282612a4a565b5090949350505050565b61290685858585612b03565b6001600160a01b03841615612500578251339060010361293f5760208481015190840151612938838989858589612c73565b5050610de0565b610de0818787878787612d97565b61295682612e80565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511561299b576126cb8282612ee5565b611388612f5b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661260957604051631afcd79f60e31b815260040160405180910390fd5b6129f46129a3565b61260b81612f7a565b60008060008351604103612a375760208401516040850151606086015160001a612a2988828585612fb4565b955095509550505050612a43565b50508151600091506002905b9250925092565b6000826003811115612a5e57612a5e613cf2565b03612a67575050565b6001826003811115612a7b57612a7b613cf2565b03612a995760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115612aad57612aad613cf2565b03612ace5760405163fce698f760e01b815260048101829052602401610b9a565b6003826003811115612ae257612ae2613cf2565b03611388576040516335e2f38360e21b815260048101829052602401610b9a565b7f4a593662ee04d27b6a00ebb31be7fe0c102c2ade82a7c5d764f2df05dc4e2800612b3085858585613083565b6001600160a01b038516612bde576000805b8451811015612bc2576000848281518110612b5f57612b5f613c6d565b6020026020010151905080846000016000888581518110612b8257612b82613c6d565b602002602001015181526020019081526020016000206000828254612ba79190613d21565b90915550612bb790508184613d21565b925050600101612b42565b5080826001016000828254612bd79190613d21565b9091555050505b6001600160a01b038416612500576000805b8451811015612c5f576000848281518110612c0d57612c0d613c6d565b6020026020010151905080846000016000888581518110612c3057612c30613c6d565b602090810291909101810151825281019190915260400160002080549190910390559190910190600101612bf0565b506001820180549190910390555050505050565b6001600160a01b0384163b15610de05760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190612cb79089908990889088908890600401613d34565b6020604051808303816000875af1925050508015612cf2575060408051601f3d908101601f19168201909252612cef91810190613d79565b60015b612d5b573d808015612d20576040519150601f19603f3d011682016040523d82523d6000602084013e612d25565b606091505b508051600003612d5357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b9a565b805181602001fd5b6001600160e01b0319811663f23a6e6160e01b1461280657604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b9a565b6001600160a01b0384163b15610de05760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190612ddb9089908990889088908890600401613d96565b6020604051808303816000875af1925050508015612e16575060408051601f3d908101601f19168201909252612e1391810190613d79565b60015b612e44573d808015612d20576040519150601f19603f3d011682016040523d82523d6000602084013e612d25565b6001600160e01b0319811663bc197c8160e01b1461280657604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b9a565b806001600160a01b03163b600003612eb657604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610b9a565b600080516020613e3683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051612f029190613df4565b600060405180830381855af49150503d8060008114612f3d576040519150601f19603f3d011682016040523d82523d6000602084013e612f42565b606091505b5091509150612f528583836132a8565b95945050505050565b34156126095760405163b398979f60e01b815260040160405180910390fd5b600080516020613e568339815191527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c45026126cb8382613b7f565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115612fef5750600091506003905082613079565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015613043573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661306f57506000925060019150829050613079565b9250600091508190505b9450945094915050565b80518251600080516020613e5683398151915291146130c25782518251604051635b05999160e01b815260048101929092526024820152604401610b9a565b3360005b84518110156131c8576020818102868101820151908601909101516001600160a01b03891615613179576000828152602086815260408083206001600160a01b038d16845290915290205481811015613152576040516303dee4c560e01b81526001600160a01b038b166004820152602481018290526044810183905260648101849052608401610b9a565b6000838152602087815260408083206001600160a01b038e16845290915290209082900390555b6001600160a01b038816156131be576000828152602086815260408083206001600160a01b038c168452909152812080548392906131b8908490613d21565b90915550505b50506001016130c6565b5083516001036132495760208401516000906020850151909150866001600160a01b0316886001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62858560405161323a929190918252602082015260400190565b60405180910390a45050610de0565b846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8787604051613298929190613e10565b60405180910390a4505050505050565b6060826132bd576132b882613304565b612499565b81511580156132d457506001600160a01b0384163b155b156132fd57604051639996b31560e01b81526001600160a01b0385166004820152602401610b9a565b5080612499565b8051156133145780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60006020828403121561333f57600080fd5b5035919050565b80356001600160a01b038116811461335d57600080fd5b919050565b6000806040838503121561337557600080fd5b61337e83613346565b946020939093013593505050565b6001600160e01b03198116811461260b57600080fd5b6000602082840312156133b457600080fd5b81356124998161338c565b60005b838110156133da5781810151838201526020016133c2565b50506000910152565b600081518084526133fb8160208601602086016133bf565b601f01601f19169290920160200192915050565b60208152600061249960208301846133e3565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561346057613460613422565b604052919050565b600082601f83011261347957600080fd5b81356001600160401b0381111561349257613492613422565b6134a5601f8201601f1916602001613438565b8181528460208386010111156134ba57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000606084860312156134ec57600080fd5b83356001600160401b038082111561350357600080fd5b61350f87838801613468565b9450602086013591508082111561352557600080fd5b5061353286828701613468565b92505061354160408501613346565b90509250925092565b60008060006060848603121561355f57600080fd5b61356884613346565b92506020840135915060408401356001600160401b0381111561358a57600080fd5b61359686828701613468565b9150509250925092565b600080600080608085870312156135b657600080fd5b8435935060208501356001600160401b03808211156135d457600080fd5b6135e088838901613468565b94506040870135935060608701359150808211156135fd57600080fd5b5061360a87828801613468565b91505092959194509250565b60006001600160401b0382111561362f5761362f613422565b5060051b60200190565b600082601f83011261364a57600080fd5b8135602061365f61365a83613616565b613438565b8083825260208201915060208460051b87010193508684111561368157600080fd5b602086015b8481101561369d5780358352918301918301613686565b509695505050505050565b600080600080600060a086880312156136c057600080fd5b6136c986613346565b94506136d760208701613346565b935060408601356001600160401b03808211156136f357600080fd5b6136ff89838a01613639565b9450606088013591508082111561371557600080fd5b61372189838a01613639565b9350608088013591508082111561373757600080fd5b5061374488828901613468565b9150509295509295909350565b60006020828403121561376357600080fd5b61249982613346565b6000806000806080858703121561378257600080fd5b61378b85613346565b9350602085013592506040850135915060608501356001600160401b038111156137b457600080fd5b61360a87828801613468565b600080604083850312156137d357600080fd5b82356001600160401b03808211156137ea57600080fd5b818501915085601f8301126137fe57600080fd5b8135602061380e61365a83613616565b82815260059290921b8401810191818101908984111561382d57600080fd5b948201945b838610156138525761384386613346565b82529482019490820190613832565b9650508601359250508082111561386857600080fd5b5061387585828601613639565b9150509250929050565b60008151808452602080850194506020840160005b838110156138b057815187529582019590820190600101613894565b509495945050505050565b602081526000612499602083018461387f565b600080604083850312156138e157600080fd5b6138ea83613346565b915060208301356001600160401b0381111561390557600080fd5b61387585828601613468565b60008060006060848603121561392657600080fd5b833592506020840135915060408401356001600160401b0381111561358a57600080fd5b60008060008060008060c0878903121561396357600080fd5b61396c87613346565b955061397a60208801613346565b94506040870135935060608701356001600160401b038082111561399d57600080fd5b6139a98a838b01613468565b94506080890135935060a08901359150808211156139c657600080fd5b506139d389828a01613468565b9150509295509295509295565b600080604083850312156139f357600080fd5b6139fc83613346565b915060208301358015158114613a1157600080fd5b809150509250929050565b60008060408385031215613a2f57600080fd5b613a3883613346565b9150613a4660208401613346565b90509250929050565b600080600080600060a08688031215613a6757600080fd5b613a7086613346565b9450613a7e60208701613346565b9350604086013592506060860135915060808601356001600160401b03811115613aa757600080fd5b61374488828901613468565b600181811c90821680613ac757607f821691505b602082108103613ae757634e487b7160e01b600052602260045260246000fd5b50919050565b60609290921b6001600160601b0319168252601482015260340190565b83815260008351613b228160208501602088016133bf565b60209201918201929092526040019392505050565b601f8211156126cb576000816000526020600020601f850160051c81016020861015613b605750805b601f850160051c820191505b81811015610de057828155600101613b6c565b81516001600160401b03811115613b9857613b98613422565b613bac81613ba68454613ab3565b84613b37565b602080601f831160018114613be15760008415613bc95750858301515b600019600386901b1c1916600185901b178555610de0565b600085815260208120601f198616915b82811015613c1057888601518255948401946001909101908401613bf1565b5085821015613c2e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600060018201613c6657613c66613c3e565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600081613c9257613c92613c3e565b506000190190565b60008351613cac8184602088016133bf565b60609390931b6001600160601b0319169190920190815260140192915050565b82815260008251613ce48160208501602087016133bf565b919091016020019392505050565b634e487b7160e01b600052602160045260246000fd5b600060208284031215613d1a57600080fd5b5051919050565b808201808211156108ea576108ea613c3e565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090613d6e908301846133e3565b979650505050505050565b600060208284031215613d8b57600080fd5b81516124998161338c565b6001600160a01b0386811682528516602082015260a060408201819052600090613dc29083018661387f565b8281036060840152613dd4818661387f565b90508281036080840152613de881856133e3565b98975050505050505050565b60008251613e068184602087016133bf565b9190910192915050565b604081526000613e23604083018561387f565b8281036020840152612f52818561387f56fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4500a26469706673582212203beae7fa062124a2dd7cd0358c764b01133cb071250938b5375769a11b7b88ce64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.