Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 19571088 | 129 days ago | IN | 0 ETH | 0.07748991 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Gluwacoin
Compiler Version
v0.8.21+commit.d9974bed
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.12; import "./core/Blacklistable.sol"; import "./core/EthlessTransfer.sol"; import "./core/Burnable.sol"; import "./core/Mintable.sol"; import "./core/ERC20Reservable.sol"; contract Gluwacoin is Blacklistable, EthlessTransfer, Burnable, Mintable, ERC20Reservable { string private _name; function initialize( address admin, uint256 supplyCap_, uint8 mintingAuthorizationThreshold_ ) external virtual initializer { __Controllable_init_unchained(admin); __ERC20_init_unchained(supplyCap_); __Mintable_init_unchained(mintingAuthorizationThreshold_); } function version() public pure virtual returns (string memory) { return "0.1"; } /** * @dev The the version parameter for the EIP712 domain based on token name. We do not need to init EIP712 anymore * */ function _EIP712Version() internal pure override returns (string memory) { return version(); } /** * @dev The the name parameter for the EIP712 domain based on token name. We do not need to init EIP712 anymore * */ function _EIP712Name() internal view override returns (string memory) { return name(); } function chainId() external view returns (uint256) { return block.chainid; } function setSupplyCap(uint256 supplyCap_) external onlyAdmin { _setSupplyCap(supplyCap_); } /** * @dev Returns the amount of tokens owned by `account` deducted by the reserved amount. */ function balanceOf( address account ) public view virtual override(ERC20Upgradeable, ERC20Reservable) returns (uint256) { return ERC20Reservable.balanceOf(account); } function _update( address from, address to, uint256 value ) internal override { require( !isBlacklisted(from) && !isBlacklisted(to), "Gluwacoin: From or To is blacklisted" ); require( balanceOf(from) >= value || from == address(0), "Gluwacoin: Insufficient balance" ); super._update(from, to, value); } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {ERC165Upgradeable} from "../utils/introspection/ERC165Upgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /// @custom:storage-location erc7201:openzeppelin.storage.AccessControl struct AccessControlStorage { mapping(bytes32 role => RoleData) _roles; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControl")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800; function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) { assembly { $.slot := AccessControlStorageLocation } } /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } function __AccessControl_init() internal onlyInitializing { } function __AccessControl_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { AccessControlStorage storage $ = _getAccessControlStorage(); return $._roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { AccessControlStorage storage $ = _getAccessControlStorage(); return $._roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { AccessControlStorage storage $ = _getAccessControlStorage(); bytes32 previousAdminRole = getRoleAdmin(role); $._roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { AccessControlStorage storage $ = _getAccessControlStorage(); if (!hasRole(role, account)) { $._roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { AccessControlStorage storage $ = _getAccessControlStorage(); if (hasRole(role, account)) { $._roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol) pragma solidity ^0.8.20; import {IAccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.sol"; import {AccessControlUpgradeable} from "../AccessControlUpgradeable.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerableUpgradeable is Initializable, IAccessControlEnumerable, AccessControlUpgradeable { using EnumerableSet for EnumerableSet.AddressSet; /// @custom:storage-location erc7201:openzeppelin.storage.AccessControlEnumerable struct AccessControlEnumerableStorage { mapping(bytes32 role => EnumerableSet.AddressSet) _roleMembers; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControlEnumerable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant AccessControlEnumerableStorageLocation = 0xc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e82371705932000; function _getAccessControlEnumerableStorage() private pure returns (AccessControlEnumerableStorage storage $) { assembly { $.slot := AccessControlEnumerableStorageLocation } } function __AccessControlEnumerable_init() internal onlyInitializing { } function __AccessControlEnumerable_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) { AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage(); return $._roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) { AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage(); return $._roleMembers[role].length(); } /** * @dev Overload {AccessControl-_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override returns (bool) { AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage(); bool granted = super._grantRole(role, account); if (granted) { $._roleMembers[role].add(account); } return granted; } /** * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) { AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage(); bool revoked = super._revokeRole(role, account); if (revoked) { $._roleMembers[role].remove(account); } return revoked; } }
// 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) (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; } }
// 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) (access/extensions/IAccessControlEnumerable.sol) pragma solidity ^0.8.20; import {IAccessControl} from "../IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// 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) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// 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/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 // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import {IERC5267} from "@openzeppelin/contracts/interfaces/IERC5267.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; abstract contract EIP712 is Initializable, IERC5267 { // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); bytes32 private constant TYPE_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; function _EIP712NameHash() internal view virtual returns (bytes32) { return keccak256(bytes(_EIP712Name())); } function _EIP712VersionHash() internal pure returns (bytes32) { return keccak256(bytes(_EIP712Version())); } function _EIP712Name() internal view virtual returns (string memory); function _EIP712Version() internal pure virtual returns (string memory); function _domainSeparatorV4() internal view returns (bytes32) { return _buildDomainSeparator(); } function _buildDomainSeparator() private view returns (bytes32) { return keccak256( abi.encode( TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this) ) ); } function _hashTypedDataV4( bytes32 structHash ) internal view virtual returns (bytes32) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } function eip712Domain() public view virtual override returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0f", _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; abstract contract GluwacoinBase { /** * @dev Value of the different domains of signature. */ uint8 internal constant _GENERIC_SIG_BURN_DOMAIN = 1; // uint8 internal constant _GENERIC_SIG_MINT_DOMAIN = 2; // Legacy signature, put as placeholder uint8 internal constant _GENERIC_SIG_TRANSFER_DOMAIN = 3; uint8 internal constant _GENERIC_SIG_RESERVE_DOMAIN = 4; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "./Controllable.sol"; contract Blacklistable is Controllable { uint8 private constant _BLACKLIST_STATUS = 1; event Blacklisted(address indexed account); event Unblacklisted(address indexed account); /** * @dev Return `true` if the account is blacklisted */ function isBlacklisted(address account) public view virtual returns (bool) { return _accountStatus[account] == _BLACKLIST_STATUS; } /** * @dev Internal function to add or remove an account to the blacklist */ function _setBlacklist(address account, uint8 accountStatus) private { _accountStatus[account] = accountStatus; } /** * @dev Add an account to the blacklist */ function blacklist( address account ) external virtual onlyOperator returns (bool) { _setBlacklist(account, _BLACKLIST_STATUS); emit Blacklisted(account); return true; } /** * @dev Remove an account to the blacklist */ function unblacklist( address account ) external virtual onlyOperator returns (bool) { _setBlacklist(account, 0); emit Unblacklisted(account); return true; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "../abstract/GluwacoinBase.sol"; import "./ERC20Upgradeable.sol"; import "../lib/Validate.sol"; import "./SignerNonce.sol"; contract Burnable is GluwacoinBase, SignerNonce, ERC20Upgradeable { event Burn(address indexed account, uint256 indexed amount); /** * @dev Allow a account to burn tokens of a account that allow it via ERC191 signature and collect fee */ function burn( address burner, uint256 amount, uint256 fee, uint256 nonce, bytes calldata sig ) external virtual returns (bool success) { unchecked { _useNonce(burner, nonce); bytes32 hash_ = keccak256( abi.encodePacked( _GENERIC_SIG_BURN_DOMAIN, block.chainid, address(this), burner, amount, fee, nonce ) ); Validate._validateSignature(hash_, burner, sig); if (fee > 0) _transfer(burner, _msgSender(), fee); } return _executeBurn(burner, amount - fee); } function burn(uint256 amount) external returns (bool) { return _executeBurn(_msgSender(), amount); } function _executeBurn( address burner, uint256 amount ) private returns (bool) { _burn(burner, amount); emit Burn(burner, amount); return true; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "@openzeppelin/contracts-upgradeable/access/extensions/AccessControlEnumerableUpgradeable.sol"; contract Controllable is AccessControlEnumerableUpgradeable { // keccak256('OPERATOR') bytes32 private constant _OPERATOR_ROLE = 0x523a704056dcd17bcf83bed8b68c59416dac1119be77755efe3bde0a64e46e0c; mapping(address => uint8) internal _accountStatus; function __Controllable_init_unchained( address account ) internal onlyInitializing { __AccessControl_init(); _setRoleAdmin(_OPERATOR_ROLE, DEFAULT_ADMIN_ROLE); _grantRole(DEFAULT_ADMIN_ROLE, account); _grantRole(_OPERATOR_ROLE, account); } /// @dev Restricted to members of the admin role. modifier onlyAdmin() { require(isAdmin(_msgSender()), "Restricted to Admins."); _; } /// @dev Restricted to members of the Operator role. modifier onlyOperator() { require(isOperator(_msgSender()), "Restricted to Operators."); _; } /// @dev Return `true` if the account belongs to the admin role. function isAdmin(address account) public view returns (bool) { return hasRole(DEFAULT_ADMIN_ROLE, account); } /// @dev Add an account to the admin role. Restricted to admins. function addAdmin(address account) external onlyAdmin { _grantRole(DEFAULT_ADMIN_ROLE, account); } /// @dev Return `true` if the account belongs to the operator role. function isOperator(address account) public view returns (bool) { return hasRole(_OPERATOR_ROLE, account); } /// @dev Add an account to the operator role. Restricted to admins. function addOperator(address account) external onlyAdmin { _grantRole(_OPERATOR_ROLE, account); } /// @dev Remove an account from the Operator role. Restricted to admins. function removeOperator(address account) external onlyAdmin { _revokeRole(_OPERATOR_ROLE, account); } /// @dev Remove oneself from the Admin role thus all other roles. function renounceAdmin() external { address sender = _msgSender(); renounceRole(DEFAULT_ADMIN_ROLE, sender); renounceRole(_OPERATOR_ROLE, sender); } /// @dev Remove oneself from the Operator role. function renounceOperator() external { renounceRole(_OPERATOR_ROLE, _msgSender()); } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; /** * @title Reservable */ import "../abstract/GluwacoinBase.sol"; import "./ERC20Upgradeable.sol"; import "../lib/Validate.sol"; import "./SignerNonce.sol"; contract ERC20Reservable is GluwacoinBase, SignerNonce, ERC20Upgradeable { enum ReservationStatus { Draft, // 0 Active, // 1 Reclaimed, // 2 Completed // 3 } struct Reservation { uint96 amount; uint96 fee; address recipient; address executor; uint64 expiryBlockNum; /// @dev to ensure the return reservation object is compatible to the current BE ReservationStatus status; } uint64 public constant MINIMUM_BLOCK_FOR_RESERVATION = 14400; // Total balance of all active reservations per address mapping(address => uint256) private _totalReserved; // Mapping of all reservations per address and nonces mapping(address => mapping(uint256 => Reservation)) private _reservation; function __Reservable_init_unchained() internal onlyInitializing {} function _reserve( address from_, address to_, address executor_, uint96 amount_, uint96 executionFee_, uint256 nonce_, uint64 deadline_ ) private { require( balanceOf(from_) >= amount_ + executionFee_, "Reservable: reserve amount exceeds balance" ); _reservation[from_][nonce_] = Reservation( amount_, executionFee_, to_, executor_, deadline_, ReservationStatus.Active ); unchecked { _totalReserved[from_] += amount_ + executionFee_; } } function reserve( address sender, address recipient, address executor, uint96 amount, uint96 fee, uint256 gluwaNonce, uint64 deadline_, bytes calldata sig ) external virtual returns (bool success) { require( executor != address(0), "Reservable: cannot execute from zero address" ); require( deadline_ >= block.number + MINIMUM_BLOCK_FOR_RESERVATION, "Reservable: invalid block expiry number" ); _useNonce(sender, gluwaNonce); bytes32 hash_ = keccak256( abi.encodePacked( _GENERIC_SIG_RESERVE_DOMAIN, block.chainid, address(this), sender, recipient, executor, amount, fee, gluwaNonce, deadline_ ) ); Validate._validateSignature(hash_, sender, sig); _reserve( sender, recipient, executor, amount, fee, gluwaNonce, deadline_ ); return true; } function reserveOf(address account_) external view returns (uint256 count) { return _totalReserved[account_]; } function getReservation( address account_, uint256 nonce_ ) external view returns (Reservation memory) { return _reservation[account_][nonce_]; } function _execute(address from_, Reservation storage reservation) private { address sender = _msgSender(); require( reservation.executor == sender || from_ == sender, "Reservable: not authorized to execute" ); require( reservation.expiryBlockNum > block.number && reservation.status == ReservationStatus.Active, "Reservable: expired or invalid reservation status" ); uint256 fee = reservation.fee; uint96 amount = reservation.amount; address recipient = reservation.recipient; address executor = reservation.executor; reservation.status = ReservationStatus.Completed; unchecked { _totalReserved[from_] -= amount + fee; } _transfer(from_, executor, fee); _transfer(from_, recipient, amount); } function execute( address from_, uint256 nonce_ ) external returns (bool success) { _execute(from_, _reservation[from_][nonce_]); return true; } function reclaim( address from_, uint256 nonce_ ) external returns (bool success) { Reservation storage reservation = _reservation[from_][nonce_]; address sender = _msgSender(); require( reservation.status == ReservationStatus.Active, "Reservable: invalid reservation status" ); require( from_ == sender || sender == reservation.executor, "Reservable: only the sender or the executor to call" ); /// @dev since the reservation.sender (form_) can reach this stage, we need to limit the ability of the address to reclaim after expiration require( reservation.expiryBlockNum <= block.number || sender == reservation.executor, "Reservable: reservation not expired or you not executor" ); reservation.status = ReservationStatus.Reclaimed; unchecked { _totalReserved[from_] -= reservation.amount + reservation.fee; } return true; } function balanceOf( address account ) public view virtual override returns (uint256 amount) { return super.balanceOf(account) - _totalReserved[account]; } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {ContextUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * */ abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors { /// @custom:storage-location erc7201:openzeppelin.storage.ERC20 struct ERC20Storage { mapping(address account => uint256) _balances; mapping(address account => mapping(address spender => uint256)) _allowances; uint256 _totalSupply; uint256 _supplyCap; } // keccak256(abi.encode(uint256(keccak256("gluwa.storage.ERC20")) - 1)) bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00; function _getERC20Storage() private pure returns (ERC20Storage storage es) { assembly { es.slot := ERC20StorageLocation } } function __ERC20_init_unchained( uint256 supplyCap_ ) internal onlyInitializing { ERC20Storage storage es = _getERC20Storage(); es._supplyCap = supplyCap_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return "Wrapped CTC"; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public pure virtual returns (string memory) { return "WCTC"; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public pure virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { _transfer(_msgSender(), to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance( address owner, address spender ) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._allowances[owner][spender]; } /** * @dev Return the supply cap. */ function supplyCap() public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._supplyCap; } /** * @dev Adjust the supply cap. */ function _setSupplyCap(uint256 supplyCap_) internal { ERC20Storage storage $ = _getERC20Storage(); require( ($._supplyCap = supplyCap_) >= $._totalSupply, "ERC20: Total supplyc can't be more than supply cap" ); } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve( address spender, uint256 value ) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom( address from, address to, uint256 value ) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows require( ($._totalSupply += value) <= $._supplyCap, "ERC20: Exceeding supply cap" ); } else { uint256 fromBalance = $._balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. $._balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. $._totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. $._balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve( address owner, address spender, uint256 value, bool emitEvent ) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } $._allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 value ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance( spender, currentAllowance, value ); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "../abstract/GluwacoinBase.sol"; import "./ERC20Upgradeable.sol"; import "../lib/Validate.sol"; import "./SignerNonce.sol"; contract EthlessTransfer is GluwacoinBase, SignerNonce, ERC20Upgradeable { /** * @dev Allow a account to transfer tokens of a account that allow it via ERC191 signature and collect fee */ function transfer( address sender, address recipient, uint256 amount, uint256 fee, uint256 gluwaNonce, bytes calldata sig ) external virtual returns (bool success) { unchecked { _useNonce(sender, gluwaNonce); bytes32 hash_ = keccak256( abi.encodePacked( _GENERIC_SIG_TRANSFER_DOMAIN, block.chainid, address(this), sender, recipient, amount, fee, gluwaNonce ) ); Validate._validateSignature(hash_, sender, sig); _transfer(sender, _msgSender(), fee); _transfer(sender, recipient, amount); return true; } } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import "../abstract/EIP712.sol"; import "./ERC20Upgradeable.sol"; import "./Controllable.sol"; abstract contract Mintable is Controllable, EIP712, ERC20Upgradeable { error ProofWasUsed(); event Mint( address indexed minter, address indexed to, uint256 indexed amount ); // keccak256("mintByAuthorization(uint256 amount,bytes32 proofBlockHash,bytes32 proofTxnHash,uint256[] gluwaNonces,uint256[] expiries,bytes[] signature)"); bytes32 private constant _MINTBYAUTHORIZATION_TYPEHASH = 0xc55f05749175b4ba324db46e3b27cb9e05ab693cb666c1a026cc96deb68d4cd9; uint8 private _mintingAuthorizationThreshold; mapping(bytes32 => uint256) private _mintingRecord; function __Mintable_init_unchained( uint8 mintingAuthorizationThreshold_ ) internal onlyInitializing { _mintingAuthorizationThreshold = mintingAuthorizationThreshold_; } /** * @dev Allow the Governance role to mint tokens for a account */ function mint( address receiver, uint256 amount, bytes32 proofBlockHash, bytes32 proofTxnHash ) external virtual onlyOperator returns (bool) { _logMintingRecord(amount, proofBlockHash, proofTxnHash); _mint(receiver, amount); emit Mint(_msgSender(), receiver, amount); return true; } function setMintingAuthorizationThreshold( uint8 newThreshold ) external onlyOperator { require(newThreshold >= 2, "Mintable: new threshold is too small"); _mintingAuthorizationThreshold = newThreshold; } function getMintingAuthorizationThreshold() external view returns (uint8) { return _mintingAuthorizationThreshold; } function mintByAuthorization( address receiver, uint256 amount, bytes32 proofBlockHash, bytes32 proofTxnHash, uint256[] calldata gluwaNonces, uint256[] calldata expiries, bytes[] calldata signatures ) private returns (bool) { uint256 numOfSig = expiries.length; require( numOfSig >= _mintingAuthorizationThreshold, "Mintable: not enough signatures" ); for (uint256 i; i < numOfSig; ) { require( receiver == _verifySignature( receiver, amount, proofBlockHash, proofTxnHash, gluwaNonces[i], expiries[i], signatures[i] ), "Mintable: receiver mismatch" ); unchecked { ++i; } } _logMintingRecord(amount, proofBlockHash, proofTxnHash); _mint(receiver, amount); emit Mint(_msgSender(), receiver, amount); return true; } function mintedAmountByProof( bytes32 proofBlockHash, bytes32 proofTxnHash ) external view returns (uint256) { return _mintingRecord[_generateProof(proofBlockHash, proofTxnHash)]; } function _logMintingRecord( uint256 amount, bytes32 proofBlockHash, bytes32 proofTxnHash ) private { bytes32 proof = _generateProof(proofBlockHash, proofTxnHash); if (_mintingRecord[proof] > 0) revert ProofWasUsed(); _mintingRecord[proof] = amount; } function _generateProof( bytes32 proofBlockHash, bytes32 proofTxnHash ) private pure returns (bytes32) { return keccak256(abi.encodePacked(proofBlockHash, proofTxnHash)); } function _verifySignature( address receiver, uint256 amount, bytes32 proofBlockHash, bytes32 proofTxnHash, uint256 gluwaNonce, uint256 expiry, bytes calldata signature ) private view returns (address) { require( expiry >= block.timestamp, "ERC20StakedVotesUpgradeable: Sig is expired" ); return ECDSA.recover( MessageHashUtils.toEthSignedMessageHash(_hashTypedDataV4( keccak256( abi.encode( _MINTBYAUTHORIZATION_TYPEHASH, receiver, amount, proofBlockHash, proofTxnHash, gluwaNonce, expiry ) ) )), signature ); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; contract SignerNonce is ContextUpgradeable { mapping(bytes32 => bool) private _nonceUsed; /** * @dev Allow sender to check if the nonce is used. */ function isNonceUsed(uint256 nonce) public view virtual returns (bool) { return _isNonceUsed(_nonceSig(_msgSender(), nonce)); } /** * @dev Allow sender to check if the nonce is used. */ function revokeSignature(uint256 nonce) external virtual returns (bool) { _nonceUsed[_nonceSig(_msgSender(), nonce)] = true; return true; } /** * @dev Check whether a nonce is used for a signer. */ function _isNonceUsed(bytes32 nonceSig) private view returns (bool) { return _nonceUsed[nonceSig]; } /** * @dev Create nonce signature. */ function _nonceSig(address signer, uint256 nonce) private pure returns (bytes32) { return keccak256(abi.encodePacked(signer, nonce)); } /** * @dev Register a nonce for a signer. */ function _useNonce(address signer, uint256 nonce) internal { bytes32 nonceSig = _nonceSig(signer, nonce); require(!_isNonceUsed(nonceSig), "SignerNonce: Invalid Nonce"); _nonceUsed[nonceSig] = true; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; /** * @dev Signature verification */ library Validate { using ECDSA for bytes32; /** * @dev Throws if given `sig` is an incorrect signature of the `sender`. */ function _validateSignature( bytes32 hash_, address sender, bytes calldata sig ) internal pure returns (bool) { require( ECDSA.recover(MessageHashUtils.toEthSignedMessageHash(hash_), sig) == sender, "Validate: invalid signature" ); return true; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","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":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"ProofWasUsed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"Blacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"Unblacklisted","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMUM_BLOCK_FOR_RESERVATION","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"blacklist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"burner","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"burn","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint256","name":"nonce_","type":"uint256"}],"name":"execute","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getMintingAuthorizationThreshold","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"},{"internalType":"uint256","name":"nonce_","type":"uint256"}],"name":"getReservation","outputs":[{"components":[{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"uint96","name":"fee","type":"uint96"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"uint64","name":"expiryBlockNum","type":"uint64"},{"internalType":"enum ERC20Reservable.ReservationStatus","name":"status","type":"uint8"}],"internalType":"struct ERC20Reservable.Reservation","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint256","name":"supplyCap_","type":"uint256"},{"internalType":"uint8","name":"mintingAuthorizationThreshold_","type":"uint8"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"isNonceUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"proofBlockHash","type":"bytes32"},{"internalType":"bytes32","name":"proofTxnHash","type":"bytes32"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"proofBlockHash","type":"bytes32"},{"internalType":"bytes32","name":"proofTxnHash","type":"bytes32"}],"name":"mintedAmountByProof","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint256","name":"nonce_","type":"uint256"}],"name":"reclaim","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"uint96","name":"fee","type":"uint96"},{"internalType":"uint256","name":"gluwaNonce","type":"uint256"},{"internalType":"uint64","name":"deadline_","type":"uint64"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"reserve","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"reserveOf","outputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"revokeSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"newThreshold","type":"uint8"}],"name":"setMintingAuthorizationThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"supplyCap_","type":"uint256"}],"name":"setSupplyCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"gluwaNonce","type":"uint256"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unblacklist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50612f77806100206000396000f3fe608060405234801561001057600080fd5b50600436106102bb5760003560e01c806375e3661e11610182578063a217fddf116100e9578063c514fd0b116100a2578063dd62ed3e1161007c578063dd62ed3e146106b4578063ed2e93b2146106c7578063f9f92be4146106da578063fe575a87146106ed57600080fd5b8063c514fd0b1461067b578063ca15c8731461068e578063d547741f146106a157600080fd5b8063a217fddf14610607578063a22ac5a91461060f578063a9059cbb1461062f578063ac8a584a14610642578063b49dc74114610655578063b6a3f59a1461066857600080fd5b80639010d07c1161013b5780639010d07c1461056657806391d148541461059157806395d89b41146105a45780639870d7fe146105c45780639a8a0592146105d75780639fa77b20146105dd57600080fd5b806375e3661e146104d5578063837e7628146104e857806384b0196e146105095780638bad0c0a146105245780638bd317eb1461052c5780638f770ad01461053f57600080fd5b806336568abe116102265780635d00bb12116101df5780635d00bb12146104635780635eda9cbc1461047657806369cd5d3b146104895780636d70f7ae1461049c57806370480275146104af57806370a08231146104c257600080fd5b806336568abe146103ed5780633b89bb86146104005780633da1f79a1461041357806342966c6814610426578063435d660d1461043957806354fd4d501461044457600080fd5b8063248a9ca311610278578063248a9ca31461038257806324d7806c14610395578063277a4373146103a85780632ab6f8db146103bb5780632f2ff15d146103c5578063313ce567146103d857600080fd5b806301ffc9a7146102c057806306fdde03146102e8578063095ea7b3146103185780630982d5b01461032b57806318160ddd1461033e57806323b872dd1461036f575b600080fd5b6102d36102ce3660046127a9565b61071c565b60405190151581526020015b60405180910390f35b60408051808201909152600b81526a577261707065642043544360a81b60208201525b6040516102df9190612819565b6102d3610326366004612843565b610747565b6102d36103393660046128b5565b61075f565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b6040519081526020016102df565b6102d361037d366004612936565b61080d565b610361610390366004612972565b610831565b6102d36103a336600461298b565b610853565b6102d36103b63660046129a6565b61085f565b6103c36108e7565b005b6103c36103d33660046129df565b610901565b60125b60405160ff90911681526020016102df565b6103c36103fb3660046129df565b610923565b6102d361040e366004612843565b61095b565b6102d3610421366004612972565b610993565b6102d3610434366004612972565b6109cb565b60fc5460ff166103db565b604080518082019091526003815262302e3160e81b602082015261030b565b6102d3610471366004612972565b6109d7565b610361610484366004612a0b565b6109fb565b6102d3610497366004612a2d565b610a22565b6102d36104aa36600461298b565b610acf565b6103c36104bd36600461298b565b610ae9565b6103616104d036600461298b565b610b1d565b6102d36104e336600461298b565b610b28565b6104f161384081565b6040516001600160401b0390911681526020016102df565b610511610b97565b6040516102df9796959493929190612a9d565b6103c3610bdd565b6102d361053a366004612843565b610c04565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0354610361565b610579610574366004612a0b565b610e46565b6040516001600160a01b0390911681526020016102df565b6102d361059f3660046129df565b610e75565b6040805180820190915260048152635743544360e01b602082015261030b565b6103c36105d236600461298b565b610ead565b46610361565b6103616105eb36600461298b565b6001600160a01b03166000908152610130602052604090205490565b610361600081565b61062261061d366004612843565b610eea565b6040516102df9190612b49565b6102d361063d366004612843565b610fd9565b6103c361065036600461298b565b610fe6565b6103c3610663366004612be2565b611023565b6103c3610676366004612972565b611145565b6103c3610689366004612c1e565b611173565b61036161069c366004612972565b61120e565b6103c36106af3660046129df565b61123b565b6103616106c2366004612c39565b611257565b6102d36106d5366004612c7a565b6112a1565b6102d36106e836600461298b565b6113f7565b6102d36106fb36600461298b565b6001600160a01b031660009081526020819052604090205460ff1660011490565b60006001600160e01b03198216635a05180f60e01b1480610741575061074182611465565b92915050565b60003361075581858561149a565b5060019392505050565b600061076b88856114a7565b604051600360f81b60208201524660218201526001600160601b031930606090811b821660418401528a811b8216605584015289901b166069820152607d8101879052609d810186905260bd810185905260009060dd016040516020818303038152906040528051906020012090506107e6818a8686611532565b506107f389335b88611602565b6107fe898989611602565b50600198975050505050505050565b60003361081b858285611661565b610826858585611602565b506001949350505050565b6000908152600080516020612f22833981519152602052604090206001015490565b60006107418183610e75565b600061086a33610acf565b61088f5760405162461bcd60e51b815260040161088690612d38565b60405180910390fd5b61089a8484846116c1565b6108a48585611713565b60405184906001600160a01b0387169033907fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f890600090a4506001949350505050565b6108ff600080516020612f0283398151915233610923565b565b61090a82610831565b61091381611749565b61091d8383611753565b50505050565b6001600160a01b038116331461094c5760405163334bd91960e11b815260040160405180910390fd5b6109568282611798565b505050565b6001600160a01b038216600090815261013160209081526040808320848452909152812061098a9084906117d4565b50600192915050565b600060016065826109a43386611989565b81526020810191909152604001600020805460ff1916911515919091179055506001919050565b600061074133836119cc565b60006107416109e63384611989565b60009081526065602052604090205460ff1690565b600060fd6000610a0b8585611a17565b815260200190815260200160002054905092915050565b6000610a2e87856114a7565b604051600160f81b60208201524660218201526001600160601b031930606090811b8216604184015289901b166055820152606981018790526089810186905260a9810185905260009060c901604051602081830303815290604052805190602001209050610a9f81898686611532565b508515610ab057610ab088336107ed565b50610ac487610abf8789612d85565b6119cc565b979650505050505050565b6000610741600080516020612f0283398151915283610e75565b610af233610853565b610b0e5760405162461bcd60e51b815260040161088690612d98565b610b19600082611753565b5050565b600061074182611a33565b6000610b3333610acf565b610b4f5760405162461bcd60e51b815260040161088690612d38565b610b5a826000611a6f565b6040516001600160a01b038316907f7534c63860313c46c473e4e98328f37017e9674e2162faf1a3ad7a96236c3b7b90600090a25060015b919050565b600060608060008060006060610bab611a9c565b610bb3611acb565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b33610be9600082610923565b610c01600080516020612f0283398151915282610923565b50565b6001600160a01b03821660009081526101316020908152604080832084845290915281208133905060016002830154600160e01b900460ff166003811115610c4e57610c4e612b33565b14610caa5760405162461bcd60e51b815260206004820152602660248201527f52657365727661626c653a20696e76616c6964207265736572766174696f6e2060448201526573746174757360d01b6064820152608401610886565b806001600160a01b0316856001600160a01b03161480610cd9575060028201546001600160a01b038281169116145b610d415760405162461bcd60e51b815260206004820152603360248201527f52657365727661626c653a206f6e6c79207468652073656e646572206f7220746044820152721a1948195e1958dd5d1bdc881d1bc818d85b1b606a1b6064820152608401610886565b600282015443600160a01b9091046001600160401b0316111580610d74575060028201546001600160a01b038281169116145b610de65760405162461bcd60e51b815260206004820152603760248201527f52657365727661626c653a207265736572766174696f6e206e6f74206578706960448201527f726564206f7220796f75206e6f74206578656375746f720000000000000000006064820152608401610886565b6002828101805460ff60e01b1916600160e01b83021790555050546001600160a01b03841660009081526101306020526040902080546001600160601b03808416600160601b909404811693909301909216909103905550600192915050565b6000828152600080516020612ec2833981519152602081905260408220610e6d9084611aed565b949350505050565b6000918252600080516020612f22833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610eb633610853565b610ed25760405162461bcd60e51b815260040161088690612d98565b610b19600080516020612f0283398151915282611753565b610f206040805160c08101825260008082526020820181905291810182905260608101829052608081018290529060a082015290565b6001600160a01b03838116600090815261013160209081526040808320868452825291829020825160c08101845281546001600160601b038082168352600160601b9091041692810192909252600181015484169282019290925260028201549283166060820152600160a01b83046001600160401b031660808201529160a0830190600160e01b900460ff166003811115610fbe57610fbe612b33565b6003811115610fcf57610fcf612b33565b9052509392505050565b600061098a338484611602565b610fef33610853565b61100b5760405162461bcd60e51b815260040161088690612d98565b610b19600080516020612f0283398151915282611798565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03166000811580156110685750825b90506000826001600160401b031660011480156110845750303b155b905081158015611092575080155b156110b05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156110da57845460ff60401b1916600160401b1785555b6110e388611af9565b6110ec87611b46565b6110f586611b72565b831561113b57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b61114e33610853565b61116a5760405162461bcd60e51b815260040161088690612d98565b610c0181611b7a565b61117c33610acf565b6111985760405162461bcd60e51b815260040161088690612d38565b60028160ff1610156111f85760405162461bcd60e51b8152602060048201526024808201527f4d696e7461626c653a206e6577207468726573686f6c6420697320746f6f20736044820152631b585b1b60e21b6064820152608401610886565b60fc805460ff191660ff92909216919091179055565b6000818152600080516020612ec283398151915260208190526040822061123490611c3a565b9392505050565b61124482610831565b61124d81611749565b61091d8383611798565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b60006001600160a01b03881661130e5760405162461bcd60e51b815260206004820152602c60248201527f52657365727661626c653a2063616e6e6f7420657865637574652066726f6d2060448201526b7a65726f206164647265737360a01b6064820152608401610886565b61131a61384043612dc7565b846001600160401b031610156113825760405162461bcd60e51b815260206004820152602760248201527f52657365727661626c653a20696e76616c696420626c6f636b2065787069727960448201526610373ab6b132b960c91b6064820152608401610886565b61138c8a866114a7565b6000600446308d8d8d8d8d8d8d6040516020016113b29a99989796959493929190612dda565b6040516020818303038152906040528051906020012090506113d6818c8686611532565b506113e68b8b8b8b8b8b8b611c44565b5060019a9950505050505050505050565b600061140233610acf565b61141e5760405162461bcd60e51b815260040161088690612d38565b611429826001611a6f565b6040516001600160a01b038316907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a2506001919050565b60006001600160e01b03198216637965db0b60e01b148061074157506301ffc9a760e01b6001600160e01b0319831614610741565b6109568383836001611e39565b60006114b38383611989565b60008181526065602052604090205490915060ff16156115155760405162461bcd60e51b815260206004820152601a60248201527f5369676e65724e6f6e63653a20496e76616c6964204e6f6e63650000000000006044820152606401610886565b6000908152606560205260409020805460ff191660011790555050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c859052603c81206001600160a01b038516906115ac9085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f2192505050565b6001600160a01b0316146108265760405162461bcd60e51b815260206004820152601b60248201527f56616c69646174653a20696e76616c6964207369676e617475726500000000006044820152606401610886565b6001600160a01b03831661162c57604051634b637e8f60e11b815260006004820152602401610886565b6001600160a01b0382166116565760405163ec442f0560e01b815260006004820152602401610886565b610956838383611f4b565b600061166d8484611257565b9050600019811461091d57818110156116b257604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610886565b61091d84848484036000611e39565b60006116cd8383611a17565b600081815260fd6020526040902054909150156116fd576040516311bb1cd760e01b815260040160405180910390fd5b600090815260fd60205260409020929092555050565b6001600160a01b03821661173d5760405163ec442f0560e01b815260006004820152602401610886565b610b1960008383611f4b565b610c01813361206c565b6000600080516020612ec28339815191528161176f85856120a5565b90508015610e6d57600085815260208390526040902061178f9085612151565b50949350505050565b6000600080516020612ec2833981519152816117b48585612166565b90508015610e6d57600085815260208390526040902061178f90856121e2565b600281015433906001600160a01b03168114806118025750806001600160a01b0316836001600160a01b0316145b61185c5760405162461bcd60e51b815260206004820152602560248201527f52657365727661626c653a206e6f7420617574686f72697a656420746f206578604482015264656375746560d81b6064820152608401610886565b600282015443600160a01b9091046001600160401b031611801561189f575060016002830154600160e01b900460ff16600381111561189d5761189d612b33565b145b6119055760405162461bcd60e51b815260206004820152603160248201527f52657365727661626c653a2065787069726564206f7220696e76616c6964207260448201527065736572766174696f6e2073746174757360781b6064820152608401610886565b8154600183015460028401805460ff60e01b198116600360e01b179091556001600160a01b038681166000908152610130602052604090208054600160601b86046001600160601b039081169616868101909103909155928116911661196c878286611602565b6119808783856001600160601b0316611602565b50505050505050565b6040516001600160601b0319606084901b166020820152603481018290526000906054015b60405160208183030381529060405280519060200120905092915050565b60006119d883836121f7565b60405182906001600160a01b038516907fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca590600090a350600192915050565b60408051602081018490529081018290526000906060016119ae565b6001600160a01b03811660009081526101306020908152604080832054600080516020612ee28339815191529092528220546107419190612d85565b6001600160a01b03919091166000908152602081905260409020805460ff191660ff909216919091179055565b6060611ac660408051808201909152600b81526a577261707065642043544360a81b602082015290565b905090565b6060611ac6604080518082019091526003815262302e3160e81b602082015290565b6000611234838361222d565b611b01612257565b611b096122a0565b611b22600080516020612f0283398151915260006122a8565b611b2d600082611753565b50610b19600080516020612f0283398151915282611753565b611b4e612257565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0355565b6111f8612257565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02547f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03829055600080516020612ee283398151915290821015610b195760405162461bcd60e51b815260206004820152603260248201527f45524332303a20546f74616c20737570706c79632063616e2774206265206d6f60448201527107265207468616e20737570706c79206361760741b6064820152608401610886565b6000610741825490565b611c4e8385612e75565b6001600160601b0316611c6088610b1d565b1015611cc15760405162461bcd60e51b815260206004820152602a60248201527f52657365727661626c653a207265736572766520616d6f756e7420657863656560448201526964732062616c616e636560b01b6064820152608401610886565b6040518060c00160405280856001600160601b03168152602001846001600160601b03168152602001876001600160a01b03168152602001866001600160a01b03168152602001826001600160401b0316815260200160016003811115611d2a57611d2a612b33565b90526001600160a01b0380891660009081526101316020908152604080832087845282529182902084518154928601516001600160601b03908116600160601b026001600160c01b0319909416911617919091178155908301516001820180549184166001600160a01b0319909216919091179055606083015160028201805460808601516001600160401b0316600160a01b026001600160e01b031990911692909416919091179290921780835560a084015191929060ff60e01b1916600160e01b836003811115611dff57611dff612b33565b02179055505050506001600160a01b03959095166000908152610130602052604090208054919092016001600160601b0316019055505050565b600080516020612ee28339815191526001600160a01b038516611e725760405163e602df0560e01b815260006004820152602401610886565b6001600160a01b038416611e9c57604051634a1406b160e11b815260006004820152602401610886565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115611f1a57836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051611f1191815260200190565b60405180910390a35b5050505050565b600080600080611f31868661230b565b925092509250611f418282612358565b5090949350505050565b611f70836001600160a01b031660009081526020819052604090205460ff1660011490565b158015611f9f5750611f9d826001600160a01b031660009081526020819052604090205460ff1660011490565b155b611ff75760405162461bcd60e51b8152602060048201526024808201527f476c757761636f696e3a2046726f6d206f7220546f20697320626c61636b6c696044820152631cdd195960e21b6064820152608401610886565b8061200184610b1d565b10158061201557506001600160a01b038316155b6120615760405162461bcd60e51b815260206004820152601f60248201527f476c757761636f696e3a20496e73756666696369656e742062616c616e6365006044820152606401610886565b610956838383612411565b6120768282610e75565b610b195760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610886565b6000600080516020612f228339815191526120c08484610e75565b612140576000848152602082815260408083206001600160a01b03871684529091529020805460ff191660011790556120f63390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610741565b6000915050610741565b5092915050565b6000611234836001600160a01b0384166125a2565b6000600080516020612f228339815191526121818484610e75565b15612140576000848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610741565b6000611234836001600160a01b0384166125f1565b6001600160a01b03821661222157604051634b637e8f60e11b815260006004820152602401610886565b610b1982600083611f4b565b600082600001828154811061224457612244612e95565b9060005260206000200154905092915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166108ff57604051631afcd79f60e31b815260040160405180910390fd5b6108ff612257565b600080516020612f2283398151915260006122c284610831565b600085815260208490526040808220600101869055519192508491839187917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a450505050565b600080600083516041036123455760208401516040850151606086015160001a612337888285856126da565b955095509550505050612351565b50508151600091506002905b9250925092565b600082600381111561236c5761236c612b33565b03612375575050565b600182600381111561238957612389612b33565b036123a75760405163f645eedf60e01b815260040160405180910390fd5b60028260038111156123bb576123bb612b33565b036123dc5760405163fce698f760e01b815260048101829052602401610886565b60038260038111156123f0576123f0612b33565b03610b19576040516335e2f38360e21b815260048101829052602401610886565b600080516020612ee28339815191526001600160a01b0384166124a0578060030154828260020160008282546124479190612dc7565b925050819055111561249b5760405162461bcd60e51b815260206004820152601b60248201527f45524332303a20457863656564696e6720737570706c792063617000000000006044820152606401610886565b612512565b6001600160a01b038416600090815260208290526040902054828110156124f35760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610886565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b03831661253057600281018054839003905561254f565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161259491815260200190565b60405180910390a350505050565b60008181526001830160205260408120546125e957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610741565b506000610741565b60008181526001830160205260408120548015612140576000612615600183612d85565b855490915060009061262990600190612d85565b905080821461268e57600086600001828154811061264957612649612e95565b906000526020600020015490508087600001848154811061266c5761266c612e95565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061269f5761269f612eab565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610741565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115612715575060009150600390508261279f565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015612769573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166127955750600092506001915082905061279f565b9250600091508190505b9450945094915050565b6000602082840312156127bb57600080fd5b81356001600160e01b03198116811461123457600080fd5b6000815180845260005b818110156127f9576020818501810151868301820152016127dd565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061123460208301846127d3565b80356001600160a01b0381168114610b9257600080fd5b6000806040838503121561285657600080fd5b61285f8361282c565b946020939093013593505050565b60008083601f84011261287f57600080fd5b5081356001600160401b0381111561289657600080fd5b6020830191508360208285010111156128ae57600080fd5b9250929050565b600080600080600080600060c0888a0312156128d057600080fd5b6128d98861282c565b96506128e76020890161282c565b955060408801359450606088013593506080880135925060a08801356001600160401b0381111561291757600080fd5b6129238a828b0161286d565b989b979a50959850939692959293505050565b60008060006060848603121561294b57600080fd5b6129548461282c565b92506129626020850161282c565b9150604084013590509250925092565b60006020828403121561298457600080fd5b5035919050565b60006020828403121561299d57600080fd5b6112348261282c565b600080600080608085870312156129bc57600080fd5b6129c58561282c565b966020860135965060408601359560600135945092505050565b600080604083850312156129f257600080fd5b82359150612a026020840161282c565b90509250929050565b60008060408385031215612a1e57600080fd5b50508035926020909101359150565b60008060008060008060a08789031215612a4657600080fd5b612a4f8761282c565b955060208701359450604087013593506060870135925060808701356001600160401b03811115612a7f57600080fd5b612a8b89828a0161286d565b979a9699509497509295939492505050565b60ff60f81b881681526000602060e081840152612abd60e084018a6127d3565b8381036040850152612acf818a6127d3565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015612b2157835183529284019291840191600101612b05565b50909c9b505050505050505050505050565b634e487b7160e01b600052602160045260246000fd5b600060c0820190506001600160601b0380845116835280602085015116602084015250604083015160018060a01b03808216604085015280606086015116606085015250506001600160401b03608084015116608083015260a083015160048110612bc457634e487b7160e01b600052602160045260246000fd5b8060a08401525092915050565b803560ff81168114610b9257600080fd5b600080600060608486031215612bf757600080fd5b612c008461282c565b925060208401359150612c1560408501612bd1565b90509250925092565b600060208284031215612c3057600080fd5b61123482612bd1565b60008060408385031215612c4c57600080fd5b612c558361282c565b9150612a026020840161282c565b80356001600160601b0381168114610b9257600080fd5b60008060008060008060008060006101008a8c031215612c9957600080fd5b612ca28a61282c565b9850612cb060208b0161282c565b9750612cbe60408b0161282c565b9650612ccc60608b01612c63565b9550612cda60808b01612c63565b945060a08a0135935060c08a01356001600160401b038082168214612cfe57600080fd5b90935060e08b01359080821115612d1457600080fd5b50612d218c828d0161286d565b915080935050809150509295985092959850929598565b60208082526018908201527f5265737472696374656420746f204f70657261746f72732e0000000000000000604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561074157610741612d6f565b6020808252601590820152742932b9ba3934b1ba32b2103a379020b236b4b7399760591b604082015260600190565b8082018082111561074157610741612d6f565b6001600160f81b031960f88c901b168152600181018a90526001600160601b031960608a811b8216602184015289811b8216603584015288811b8216604984015287901b16605d8201526001600160a01b031960a086811b8216607184015285901b16607d8201526000836089830152612e6360a983018460c01b6001600160c01b0319169052565b5060b1019a9950505050505050505050565b6001600160601b0381811683821601908082111561214a5761214a612d6f565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fdfec1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e8237170593200052c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00523a704056dcd17bcf83bed8b68c59416dac1119be77755efe3bde0a64e46e0c02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800a2646970667358221220688ca823e0e9e6db5498ef93be28d61048924287e00b56fce2645c4a47f1893b64736f6c63430008150033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102bb5760003560e01c806375e3661e11610182578063a217fddf116100e9578063c514fd0b116100a2578063dd62ed3e1161007c578063dd62ed3e146106b4578063ed2e93b2146106c7578063f9f92be4146106da578063fe575a87146106ed57600080fd5b8063c514fd0b1461067b578063ca15c8731461068e578063d547741f146106a157600080fd5b8063a217fddf14610607578063a22ac5a91461060f578063a9059cbb1461062f578063ac8a584a14610642578063b49dc74114610655578063b6a3f59a1461066857600080fd5b80639010d07c1161013b5780639010d07c1461056657806391d148541461059157806395d89b41146105a45780639870d7fe146105c45780639a8a0592146105d75780639fa77b20146105dd57600080fd5b806375e3661e146104d5578063837e7628146104e857806384b0196e146105095780638bad0c0a146105245780638bd317eb1461052c5780638f770ad01461053f57600080fd5b806336568abe116102265780635d00bb12116101df5780635d00bb12146104635780635eda9cbc1461047657806369cd5d3b146104895780636d70f7ae1461049c57806370480275146104af57806370a08231146104c257600080fd5b806336568abe146103ed5780633b89bb86146104005780633da1f79a1461041357806342966c6814610426578063435d660d1461043957806354fd4d501461044457600080fd5b8063248a9ca311610278578063248a9ca31461038257806324d7806c14610395578063277a4373146103a85780632ab6f8db146103bb5780632f2ff15d146103c5578063313ce567146103d857600080fd5b806301ffc9a7146102c057806306fdde03146102e8578063095ea7b3146103185780630982d5b01461032b57806318160ddd1461033e57806323b872dd1461036f575b600080fd5b6102d36102ce3660046127a9565b61071c565b60405190151581526020015b60405180910390f35b60408051808201909152600b81526a577261707065642043544360a81b60208201525b6040516102df9190612819565b6102d3610326366004612843565b610747565b6102d36103393660046128b5565b61075f565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b6040519081526020016102df565b6102d361037d366004612936565b61080d565b610361610390366004612972565b610831565b6102d36103a336600461298b565b610853565b6102d36103b63660046129a6565b61085f565b6103c36108e7565b005b6103c36103d33660046129df565b610901565b60125b60405160ff90911681526020016102df565b6103c36103fb3660046129df565b610923565b6102d361040e366004612843565b61095b565b6102d3610421366004612972565b610993565b6102d3610434366004612972565b6109cb565b60fc5460ff166103db565b604080518082019091526003815262302e3160e81b602082015261030b565b6102d3610471366004612972565b6109d7565b610361610484366004612a0b565b6109fb565b6102d3610497366004612a2d565b610a22565b6102d36104aa36600461298b565b610acf565b6103c36104bd36600461298b565b610ae9565b6103616104d036600461298b565b610b1d565b6102d36104e336600461298b565b610b28565b6104f161384081565b6040516001600160401b0390911681526020016102df565b610511610b97565b6040516102df9796959493929190612a9d565b6103c3610bdd565b6102d361053a366004612843565b610c04565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0354610361565b610579610574366004612a0b565b610e46565b6040516001600160a01b0390911681526020016102df565b6102d361059f3660046129df565b610e75565b6040805180820190915260048152635743544360e01b602082015261030b565b6103c36105d236600461298b565b610ead565b46610361565b6103616105eb36600461298b565b6001600160a01b03166000908152610130602052604090205490565b610361600081565b61062261061d366004612843565b610eea565b6040516102df9190612b49565b6102d361063d366004612843565b610fd9565b6103c361065036600461298b565b610fe6565b6103c3610663366004612be2565b611023565b6103c3610676366004612972565b611145565b6103c3610689366004612c1e565b611173565b61036161069c366004612972565b61120e565b6103c36106af3660046129df565b61123b565b6103616106c2366004612c39565b611257565b6102d36106d5366004612c7a565b6112a1565b6102d36106e836600461298b565b6113f7565b6102d36106fb36600461298b565b6001600160a01b031660009081526020819052604090205460ff1660011490565b60006001600160e01b03198216635a05180f60e01b1480610741575061074182611465565b92915050565b60003361075581858561149a565b5060019392505050565b600061076b88856114a7565b604051600360f81b60208201524660218201526001600160601b031930606090811b821660418401528a811b8216605584015289901b166069820152607d8101879052609d810186905260bd810185905260009060dd016040516020818303038152906040528051906020012090506107e6818a8686611532565b506107f389335b88611602565b6107fe898989611602565b50600198975050505050505050565b60003361081b858285611661565b610826858585611602565b506001949350505050565b6000908152600080516020612f22833981519152602052604090206001015490565b60006107418183610e75565b600061086a33610acf565b61088f5760405162461bcd60e51b815260040161088690612d38565b60405180910390fd5b61089a8484846116c1565b6108a48585611713565b60405184906001600160a01b0387169033907fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f890600090a4506001949350505050565b6108ff600080516020612f0283398151915233610923565b565b61090a82610831565b61091381611749565b61091d8383611753565b50505050565b6001600160a01b038116331461094c5760405163334bd91960e11b815260040160405180910390fd5b6109568282611798565b505050565b6001600160a01b038216600090815261013160209081526040808320848452909152812061098a9084906117d4565b50600192915050565b600060016065826109a43386611989565b81526020810191909152604001600020805460ff1916911515919091179055506001919050565b600061074133836119cc565b60006107416109e63384611989565b60009081526065602052604090205460ff1690565b600060fd6000610a0b8585611a17565b815260200190815260200160002054905092915050565b6000610a2e87856114a7565b604051600160f81b60208201524660218201526001600160601b031930606090811b8216604184015289901b166055820152606981018790526089810186905260a9810185905260009060c901604051602081830303815290604052805190602001209050610a9f81898686611532565b508515610ab057610ab088336107ed565b50610ac487610abf8789612d85565b6119cc565b979650505050505050565b6000610741600080516020612f0283398151915283610e75565b610af233610853565b610b0e5760405162461bcd60e51b815260040161088690612d98565b610b19600082611753565b5050565b600061074182611a33565b6000610b3333610acf565b610b4f5760405162461bcd60e51b815260040161088690612d38565b610b5a826000611a6f565b6040516001600160a01b038316907f7534c63860313c46c473e4e98328f37017e9674e2162faf1a3ad7a96236c3b7b90600090a25060015b919050565b600060608060008060006060610bab611a9c565b610bb3611acb565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b33610be9600082610923565b610c01600080516020612f0283398151915282610923565b50565b6001600160a01b03821660009081526101316020908152604080832084845290915281208133905060016002830154600160e01b900460ff166003811115610c4e57610c4e612b33565b14610caa5760405162461bcd60e51b815260206004820152602660248201527f52657365727661626c653a20696e76616c6964207265736572766174696f6e2060448201526573746174757360d01b6064820152608401610886565b806001600160a01b0316856001600160a01b03161480610cd9575060028201546001600160a01b038281169116145b610d415760405162461bcd60e51b815260206004820152603360248201527f52657365727661626c653a206f6e6c79207468652073656e646572206f7220746044820152721a1948195e1958dd5d1bdc881d1bc818d85b1b606a1b6064820152608401610886565b600282015443600160a01b9091046001600160401b0316111580610d74575060028201546001600160a01b038281169116145b610de65760405162461bcd60e51b815260206004820152603760248201527f52657365727661626c653a207265736572766174696f6e206e6f74206578706960448201527f726564206f7220796f75206e6f74206578656375746f720000000000000000006064820152608401610886565b6002828101805460ff60e01b1916600160e01b83021790555050546001600160a01b03841660009081526101306020526040902080546001600160601b03808416600160601b909404811693909301909216909103905550600192915050565b6000828152600080516020612ec2833981519152602081905260408220610e6d9084611aed565b949350505050565b6000918252600080516020612f22833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b610eb633610853565b610ed25760405162461bcd60e51b815260040161088690612d98565b610b19600080516020612f0283398151915282611753565b610f206040805160c08101825260008082526020820181905291810182905260608101829052608081018290529060a082015290565b6001600160a01b03838116600090815261013160209081526040808320868452825291829020825160c08101845281546001600160601b038082168352600160601b9091041692810192909252600181015484169282019290925260028201549283166060820152600160a01b83046001600160401b031660808201529160a0830190600160e01b900460ff166003811115610fbe57610fbe612b33565b6003811115610fcf57610fcf612b33565b9052509392505050565b600061098a338484611602565b610fef33610853565b61100b5760405162461bcd60e51b815260040161088690612d98565b610b19600080516020612f0283398151915282611798565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03166000811580156110685750825b90506000826001600160401b031660011480156110845750303b155b905081158015611092575080155b156110b05760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156110da57845460ff60401b1916600160401b1785555b6110e388611af9565b6110ec87611b46565b6110f586611b72565b831561113b57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b61114e33610853565b61116a5760405162461bcd60e51b815260040161088690612d98565b610c0181611b7a565b61117c33610acf565b6111985760405162461bcd60e51b815260040161088690612d38565b60028160ff1610156111f85760405162461bcd60e51b8152602060048201526024808201527f4d696e7461626c653a206e6577207468726573686f6c6420697320746f6f20736044820152631b585b1b60e21b6064820152608401610886565b60fc805460ff191660ff92909216919091179055565b6000818152600080516020612ec283398151915260208190526040822061123490611c3a565b9392505050565b61124482610831565b61124d81611749565b61091d8383611798565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b60006001600160a01b03881661130e5760405162461bcd60e51b815260206004820152602c60248201527f52657365727661626c653a2063616e6e6f7420657865637574652066726f6d2060448201526b7a65726f206164647265737360a01b6064820152608401610886565b61131a61384043612dc7565b846001600160401b031610156113825760405162461bcd60e51b815260206004820152602760248201527f52657365727661626c653a20696e76616c696420626c6f636b2065787069727960448201526610373ab6b132b960c91b6064820152608401610886565b61138c8a866114a7565b6000600446308d8d8d8d8d8d8d6040516020016113b29a99989796959493929190612dda565b6040516020818303038152906040528051906020012090506113d6818c8686611532565b506113e68b8b8b8b8b8b8b611c44565b5060019a9950505050505050505050565b600061140233610acf565b61141e5760405162461bcd60e51b815260040161088690612d38565b611429826001611a6f565b6040516001600160a01b038316907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a2506001919050565b60006001600160e01b03198216637965db0b60e01b148061074157506301ffc9a760e01b6001600160e01b0319831614610741565b6109568383836001611e39565b60006114b38383611989565b60008181526065602052604090205490915060ff16156115155760405162461bcd60e51b815260206004820152601a60248201527f5369676e65724e6f6e63653a20496e76616c6964204e6f6e63650000000000006044820152606401610886565b6000908152606560205260409020805460ff191660011790555050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c859052603c81206001600160a01b038516906115ac9085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f2192505050565b6001600160a01b0316146108265760405162461bcd60e51b815260206004820152601b60248201527f56616c69646174653a20696e76616c6964207369676e617475726500000000006044820152606401610886565b6001600160a01b03831661162c57604051634b637e8f60e11b815260006004820152602401610886565b6001600160a01b0382166116565760405163ec442f0560e01b815260006004820152602401610886565b610956838383611f4b565b600061166d8484611257565b9050600019811461091d57818110156116b257604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610886565b61091d84848484036000611e39565b60006116cd8383611a17565b600081815260fd6020526040902054909150156116fd576040516311bb1cd760e01b815260040160405180910390fd5b600090815260fd60205260409020929092555050565b6001600160a01b03821661173d5760405163ec442f0560e01b815260006004820152602401610886565b610b1960008383611f4b565b610c01813361206c565b6000600080516020612ec28339815191528161176f85856120a5565b90508015610e6d57600085815260208390526040902061178f9085612151565b50949350505050565b6000600080516020612ec2833981519152816117b48585612166565b90508015610e6d57600085815260208390526040902061178f90856121e2565b600281015433906001600160a01b03168114806118025750806001600160a01b0316836001600160a01b0316145b61185c5760405162461bcd60e51b815260206004820152602560248201527f52657365727661626c653a206e6f7420617574686f72697a656420746f206578604482015264656375746560d81b6064820152608401610886565b600282015443600160a01b9091046001600160401b031611801561189f575060016002830154600160e01b900460ff16600381111561189d5761189d612b33565b145b6119055760405162461bcd60e51b815260206004820152603160248201527f52657365727661626c653a2065787069726564206f7220696e76616c6964207260448201527065736572766174696f6e2073746174757360781b6064820152608401610886565b8154600183015460028401805460ff60e01b198116600360e01b179091556001600160a01b038681166000908152610130602052604090208054600160601b86046001600160601b039081169616868101909103909155928116911661196c878286611602565b6119808783856001600160601b0316611602565b50505050505050565b6040516001600160601b0319606084901b166020820152603481018290526000906054015b60405160208183030381529060405280519060200120905092915050565b60006119d883836121f7565b60405182906001600160a01b038516907fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca590600090a350600192915050565b60408051602081018490529081018290526000906060016119ae565b6001600160a01b03811660009081526101306020908152604080832054600080516020612ee28339815191529092528220546107419190612d85565b6001600160a01b03919091166000908152602081905260409020805460ff191660ff909216919091179055565b6060611ac660408051808201909152600b81526a577261707065642043544360a81b602082015290565b905090565b6060611ac6604080518082019091526003815262302e3160e81b602082015290565b6000611234838361222d565b611b01612257565b611b096122a0565b611b22600080516020612f0283398151915260006122a8565b611b2d600082611753565b50610b19600080516020612f0283398151915282611753565b611b4e612257565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0355565b6111f8612257565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02547f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03829055600080516020612ee283398151915290821015610b195760405162461bcd60e51b815260206004820152603260248201527f45524332303a20546f74616c20737570706c79632063616e2774206265206d6f60448201527107265207468616e20737570706c79206361760741b6064820152608401610886565b6000610741825490565b611c4e8385612e75565b6001600160601b0316611c6088610b1d565b1015611cc15760405162461bcd60e51b815260206004820152602a60248201527f52657365727661626c653a207265736572766520616d6f756e7420657863656560448201526964732062616c616e636560b01b6064820152608401610886565b6040518060c00160405280856001600160601b03168152602001846001600160601b03168152602001876001600160a01b03168152602001866001600160a01b03168152602001826001600160401b0316815260200160016003811115611d2a57611d2a612b33565b90526001600160a01b0380891660009081526101316020908152604080832087845282529182902084518154928601516001600160601b03908116600160601b026001600160c01b0319909416911617919091178155908301516001820180549184166001600160a01b0319909216919091179055606083015160028201805460808601516001600160401b0316600160a01b026001600160e01b031990911692909416919091179290921780835560a084015191929060ff60e01b1916600160e01b836003811115611dff57611dff612b33565b02179055505050506001600160a01b03959095166000908152610130602052604090208054919092016001600160601b0316019055505050565b600080516020612ee28339815191526001600160a01b038516611e725760405163e602df0560e01b815260006004820152602401610886565b6001600160a01b038416611e9c57604051634a1406b160e11b815260006004820152602401610886565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115611f1a57836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051611f1191815260200190565b60405180910390a35b5050505050565b600080600080611f31868661230b565b925092509250611f418282612358565b5090949350505050565b611f70836001600160a01b031660009081526020819052604090205460ff1660011490565b158015611f9f5750611f9d826001600160a01b031660009081526020819052604090205460ff1660011490565b155b611ff75760405162461bcd60e51b8152602060048201526024808201527f476c757761636f696e3a2046726f6d206f7220546f20697320626c61636b6c696044820152631cdd195960e21b6064820152608401610886565b8061200184610b1d565b10158061201557506001600160a01b038316155b6120615760405162461bcd60e51b815260206004820152601f60248201527f476c757761636f696e3a20496e73756666696369656e742062616c616e6365006044820152606401610886565b610956838383612411565b6120768282610e75565b610b195760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610886565b6000600080516020612f228339815191526120c08484610e75565b612140576000848152602082815260408083206001600160a01b03871684529091529020805460ff191660011790556120f63390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610741565b6000915050610741565b5092915050565b6000611234836001600160a01b0384166125a2565b6000600080516020612f228339815191526121818484610e75565b15612140576000848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610741565b6000611234836001600160a01b0384166125f1565b6001600160a01b03821661222157604051634b637e8f60e11b815260006004820152602401610886565b610b1982600083611f4b565b600082600001828154811061224457612244612e95565b9060005260206000200154905092915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166108ff57604051631afcd79f60e31b815260040160405180910390fd5b6108ff612257565b600080516020612f2283398151915260006122c284610831565b600085815260208490526040808220600101869055519192508491839187917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a450505050565b600080600083516041036123455760208401516040850151606086015160001a612337888285856126da565b955095509550505050612351565b50508151600091506002905b9250925092565b600082600381111561236c5761236c612b33565b03612375575050565b600182600381111561238957612389612b33565b036123a75760405163f645eedf60e01b815260040160405180910390fd5b60028260038111156123bb576123bb612b33565b036123dc5760405163fce698f760e01b815260048101829052602401610886565b60038260038111156123f0576123f0612b33565b03610b19576040516335e2f38360e21b815260048101829052602401610886565b600080516020612ee28339815191526001600160a01b0384166124a0578060030154828260020160008282546124479190612dc7565b925050819055111561249b5760405162461bcd60e51b815260206004820152601b60248201527f45524332303a20457863656564696e6720737570706c792063617000000000006044820152606401610886565b612512565b6001600160a01b038416600090815260208290526040902054828110156124f35760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610886565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b03831661253057600281018054839003905561254f565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161259491815260200190565b60405180910390a350505050565b60008181526001830160205260408120546125e957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610741565b506000610741565b60008181526001830160205260408120548015612140576000612615600183612d85565b855490915060009061262990600190612d85565b905080821461268e57600086600001828154811061264957612649612e95565b906000526020600020015490508087600001848154811061266c5761266c612e95565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061269f5761269f612eab565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610741565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115612715575060009150600390508261279f565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015612769573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166127955750600092506001915082905061279f565b9250600091508190505b9450945094915050565b6000602082840312156127bb57600080fd5b81356001600160e01b03198116811461123457600080fd5b6000815180845260005b818110156127f9576020818501810151868301820152016127dd565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061123460208301846127d3565b80356001600160a01b0381168114610b9257600080fd5b6000806040838503121561285657600080fd5b61285f8361282c565b946020939093013593505050565b60008083601f84011261287f57600080fd5b5081356001600160401b0381111561289657600080fd5b6020830191508360208285010111156128ae57600080fd5b9250929050565b600080600080600080600060c0888a0312156128d057600080fd5b6128d98861282c565b96506128e76020890161282c565b955060408801359450606088013593506080880135925060a08801356001600160401b0381111561291757600080fd5b6129238a828b0161286d565b989b979a50959850939692959293505050565b60008060006060848603121561294b57600080fd5b6129548461282c565b92506129626020850161282c565b9150604084013590509250925092565b60006020828403121561298457600080fd5b5035919050565b60006020828403121561299d57600080fd5b6112348261282c565b600080600080608085870312156129bc57600080fd5b6129c58561282c565b966020860135965060408601359560600135945092505050565b600080604083850312156129f257600080fd5b82359150612a026020840161282c565b90509250929050565b60008060408385031215612a1e57600080fd5b50508035926020909101359150565b60008060008060008060a08789031215612a4657600080fd5b612a4f8761282c565b955060208701359450604087013593506060870135925060808701356001600160401b03811115612a7f57600080fd5b612a8b89828a0161286d565b979a9699509497509295939492505050565b60ff60f81b881681526000602060e081840152612abd60e084018a6127d3565b8381036040850152612acf818a6127d3565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015612b2157835183529284019291840191600101612b05565b50909c9b505050505050505050505050565b634e487b7160e01b600052602160045260246000fd5b600060c0820190506001600160601b0380845116835280602085015116602084015250604083015160018060a01b03808216604085015280606086015116606085015250506001600160401b03608084015116608083015260a083015160048110612bc457634e487b7160e01b600052602160045260246000fd5b8060a08401525092915050565b803560ff81168114610b9257600080fd5b600080600060608486031215612bf757600080fd5b612c008461282c565b925060208401359150612c1560408501612bd1565b90509250925092565b600060208284031215612c3057600080fd5b61123482612bd1565b60008060408385031215612c4c57600080fd5b612c558361282c565b9150612a026020840161282c565b80356001600160601b0381168114610b9257600080fd5b60008060008060008060008060006101008a8c031215612c9957600080fd5b612ca28a61282c565b9850612cb060208b0161282c565b9750612cbe60408b0161282c565b9650612ccc60608b01612c63565b9550612cda60808b01612c63565b945060a08a0135935060c08a01356001600160401b038082168214612cfe57600080fd5b90935060e08b01359080821115612d1457600080fd5b50612d218c828d0161286d565b915080935050809150509295985092959850929598565b60208082526018908201527f5265737472696374656420746f204f70657261746f72732e0000000000000000604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561074157610741612d6f565b6020808252601590820152742932b9ba3934b1ba32b2103a379020b236b4b7399760591b604082015260600190565b8082018082111561074157610741612d6f565b6001600160f81b031960f88c901b168152600181018a90526001600160601b031960608a811b8216602184015289811b8216603584015288811b8216604984015287901b16605d8201526001600160a01b031960a086811b8216607184015285901b16607d8201526000836089830152612e6360a983018460c01b6001600160c01b0319169052565b5060b1019a9950505050505050505050565b6001600160601b0381811683821601908082111561214a5761214a612d6f565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fdfec1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e8237170593200052c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00523a704056dcd17bcf83bed8b68c59416dac1119be77755efe3bde0a64e46e0c02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800a2646970667358221220688ca823e0e9e6db5498ef93be28d61048924287e00b56fce2645c4a47f1893b64736f6c63430008150033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.