Contract Overview
Balance:
0 GLMR
GLMR Value:
$0.00
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Contract Name:
EXRInventoryController
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/metatx/ERC2771Context.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "./interfaces/IEXRMintPass.sol"; import "./interfaces/IEXRInventory.sol"; import "./extensions/CouponSystem.sol"; error InventoryInsufficientPassBalance(); error InventoryCategoryExists(); error InventoryUnapprovedBurn(); error InventoryInvalidCoupon(); error InventoryZeroAddress(); error InventoryReusedSeed(); /** * @title EXR Inventory Controller * @author RacerDev * @notice This contract controls the distribution of EXRInventory items for the EXR ecosystem. * @dev Because Chainlink's VRF is not available at the time of development, random number * generation is aided by a verifiably random seed generated off-chain. * @dev This contract caters to the existing Inventory Items at the time of launch. If additional * items need to be added, this contract should be replaced with a newer version. */ contract EXRInventoryController is ERC2771Context, AccessControl, Pausable, ReentrancyGuard, CouponSystem { bytes32 public constant SYS_ADMIN_ROLE = keccak256("SYS_ADMIN_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); uint256 public constant inventoryPassId = 3; mapping(bytes32 => bool) public usedSeeds; struct Category { uint8 exists; uint8 id; uint8[9] tokenIds; } Category[] public categories; IEXRMintPass public mintpassContract; IEXRInventory public inventoryContract; event InventoryUpdateMintpassInterface(address contractAddress); event InventoryUpdateInventoryInterface(address contractAddress); event InventoryItemsClaimed(uint256[] ids, uint256[] amounts); event InventoryRewardClaimed(address indexed user, uint256 qty); event InventoryCategoryAdded(uint256 category); event InventoryCategoryRemoved(uint8 category); event InventoryCategoryDoesNotExist(uint8 category); event AdminSignerUpdated(address signer); constructor(address adminSigner, address trustedForwarder) CouponSystem(adminSigner) ERC2771Context(trustedForwarder) { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(SYS_ADMIN_ROLE, msg.sender); _grantRole(PAUSER_ROLE, msg.sender); } /* * ===================================== EXTERNAL */ /** * @notice Allow users with a valid coupon to claim Inventory Items * @dev Mechanism for players to claim inventory items as a reward * @param seed 32-byte hash of the random seed * @param qty The number of inventory items to claim * @param coupon The decoded r,s,v components of the signature */ function claimRewardItems( bytes32 seed, uint256 qty, Coupon calldata coupon ) external whenNotPaused nonReentrant hasValidOrigin { if (usedSeeds[seed]) revert InventoryReusedSeed(); usedSeeds[seed] = true; bytes32 digest = keccak256( abi.encode(address(this), block.chainid, CouponType.Reward, qty, seed, _msgSender()) ); if (!_verifyCoupon(digest, coupon)) revert InventoryInvalidCoupon(); _claimRandomItems(seed, qty); emit InventoryRewardClaimed(_msgSender(), qty); } /** * @notice Allows the holder of an Inventory Mint Pass to exchange it for Inventory Items * @dev Caller must have a valid Coupon containing a seed distributed by the EXR API * @param seed 32-byte hash of the random seed * @param qty The number of inventory items to claim * @param coupon The decoded r,s,v components of the signature */ function burnToRedeemInventoryItems( bytes32 seed, uint256 qty, Coupon calldata coupon ) external whenNotPaused nonReentrant hasValidOrigin { if (mintpassContract.balanceOf(_msgSender(), inventoryPassId) == 0) revert InventoryInsufficientPassBalance(); if (usedSeeds[seed]) revert InventoryReusedSeed(); usedSeeds[seed] = true; bytes32 digest = keccak256( abi.encode(address(this), block.chainid, CouponType.Inventory, qty, seed, _msgSender()) ); if (!_verifyCoupon(digest, coupon)) revert InventoryInvalidCoupon(); mintpassContract.authorizedBurn(_msgSender(), inventoryPassId); _claimRandomItems(seed, qty); } /* * ===================================== EXTERNAL | ADMIN */ /** * @notice Allows an Admin user to create the {mintpassContract} interface * @param mintpass Address of the Mintpass contract */ function setMintpassContract(address mintpass) external onlyRole(SYS_ADMIN_ROLE) { if (mintpass == address(0)) revert InventoryZeroAddress(); mintpassContract = IEXRMintPass(mintpass); emit InventoryUpdateMintpassInterface(mintpass); } /** * @notice Allows an Admin user to create the {inventoryContract} interface * @param inventory Address of the Inventory Contract */ function setInventoryContract(address inventory) external onlyRole(SYS_ADMIN_ROLE) { if (inventory == address(0)) revert InventoryZeroAddress(); inventoryContract = IEXRInventory(inventory); emit InventoryUpdateInventoryInterface(inventory); } /** * @dev Admin can replace signer public address from signer's keypair * @param newSigner public address of the signer's keypair */ function updateAdminSigner(address newSigner) external onlyRole(SYS_ADMIN_ROLE) { _replaceSigner(newSigner); emit AdminSignerUpdated(newSigner); } /** * @notice Allows an Admin user to add a category of Inventory Items * @dev Manually increments the category count required for looping through the categories * @param categoryId the category index for accessing the {categoryToIds} array * @param ids the token IDs to add to the category */ function addCategory(uint8 categoryId, uint8[9] calldata ids) external onlyRole(SYS_ADMIN_ROLE) { for (uint256 i; i < categories.length; i++) { if (categories[i].id == categoryId) revert InventoryCategoryExists(); } categories.push(Category({id: categoryId, exists: 1, tokenIds: ids})); emit InventoryCategoryAdded(categoryId); } /** * @notice Retrieves a category, including its ID and the tokenIDs array * @dev Convenience function for reviewing existing categories * @param categoryId The ID of the category to be retrieved * @return The category, along with its token IDs */ function getCategory(uint256 categoryId) external view returns (Category memory) { return categories[categoryId]; } /** * @notice Allows an admin user to remove a category of inventory items * @dev the {categories} array acts like an unordered list. Removing an item replaces it with * the last item in the array and removes the redundant last item * @dev The category identifier can be an integer greater than the length of the {categories} * array * @param category The ID of the category to remove (this is not the index in the array) */ function removeCategory(uint8 category) external onlyRole(SYS_ADMIN_ROLE) { bool removed; for (uint256 i; i < categories.length; i++) { if (categories[i].id == category) { categories[i] = categories[categories.length - 1]; categories.pop(); removed = true; emit InventoryCategoryRemoved(category); break; } } if (!removed) { emit InventoryCategoryDoesNotExist(category); } } /** * @notice Allows a user with the PAUSER_ROLE to pause the contract * @dev This can be used to deprecate the contract if it's replaced */ function pause() external onlyRole(PAUSER_ROLE) { _pause(); } /** * @notice Allows a user with the PAUSER_ROLE to unpause the contract */ function unpause() external onlyRole(PAUSER_ROLE) { _unpause(); } /* * ===================================== INTERNAL */ /** * @notice Claim random tokens * @dev Uses the verified seed along with block data to select random token IDs * @dev {categories} acts like an unordered list due the removal of a category by replacing * with the last category in the array. The order does not matter however * as each category has an equal chance of being selected, and categories are removed * by referencind the {id} property of the struct. * @param seed 32-byte hash of the random seed * @param amount The number of tokens to mint */ function _claimRandomItems(bytes32 seed, uint256 amount) internal { uint256[] memory ids = new uint256[](amount); uint256[] memory amounts = new uint256[](amount); for (uint256 i; i < amount; i++) { // Every category has an equal chance of being selected uint256 randomCategorySelector = (uint256( keccak256(abi.encode(seed, blockhash(block.number - 1), block.basefee, i)) ) % (categories.length * 100)) + 1; uint256 id; for (uint256 ii; ii < categories.length; ii++) { if (randomCategorySelector < (ii + 1) * 100) { id = _selectIdByRarity(randomCategorySelector, ii); break; } } ids[i] = id; amounts[i] = 1; } inventoryContract.mintBatch(_msgSender(), ids, amounts, ""); emit InventoryItemsClaimed(ids, amounts); } /** * @notice Selects an id from the category based on rarity * @dev Uses the seed and category ID to generate randomness * @dev Tiers: Common (50% chance), Mid (35% chance), rare (15% chance) * @param seed 32-byte hash of the random seed * @param category the item category to select from */ function _selectIdByRarity(uint256 seed, uint256 category) internal view returns (uint256) { uint256 randomIdSelector = (uint256(keccak256(abi.encode(seed, category))) % 3000) + 1; uint8[9] memory options = categories[category].tokenIds; if (randomIdSelector > 2500) { return options[0]; // common ( 2500 - 3000) } else if (randomIdSelector > 2000) { return options[1]; // common (2000 - 2500) } else if (randomIdSelector > 1500) { return options[2]; // common ( 1500 - 2000) } else if (randomIdSelector > 1150) { return options[3]; // mid (1150 - 1500) } else if (randomIdSelector > 800) { return options[4]; // mid (800 - 1150) } else if (randomIdSelector > 450) { return options[5]; // mid ( 450 - 800) } else if (randomIdSelector > 300) { return options[6]; // rare ( 300 - 450 ) } else if (randomIdSelector > 150) { return options[7]; // rare ( 150 - 300) } else { return options[8]; // rare ( 0 - 150) } } // ======================================================== MODIFIERS /** * @dev Only allow contract calls from Biconomy's trusted forwarder */ modifier hasValidOrigin() { require( isTrustedForwarder(msg.sender) || msg.sender == tx.origin, "Non-trusted forwarder contract not allowed" ); _; } // ======================================================== OVERRIDES /** * @dev Override Context's _msgSender() to enable meta transactions for Biconomy * relayer protocol, which allows for gasless TXs */ function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address) { return ERC2771Context._msgSender(); } /** * @dev Override Context's _msgData(). This function is not used, but is required * as an override */ function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (metatx/ERC2771Context.sol) pragma solidity ^0.8.9; import "../utils/Context.sol"; /** * @dev Context variant with ERC2771 support. */ abstract contract ERC2771Context is Context { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable _trustedForwarder; /// @custom:oz-upgrades-unsafe-allow constructor constructor(address trustedForwarder) { _trustedForwarder = trustedForwarder; } function isTrustedForwarder(address forwarder) public view virtual returns (bool) { return forwarder == _trustedForwarder; } function _msgSender() internal view virtual override returns (address sender) { if (isTrustedForwarder(msg.sender)) { // The assembly code is more direct than the Solidity version using `abi.decode`. assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) } } else { return super._msgSender(); } } function _msgData() internal view virtual override returns (bytes calldata) { if (isTrustedForwarder(msg.sender)) { return msg.data[:msg.data.length - 20]; } else { return super._msgData(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.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: * * ``` * 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}: * * ``` * 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. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @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 override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @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 override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override 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. */ function revokeRole(bytes32 role, address account) public virtual override 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 `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; interface IEXRMintPass { function balanceOf(address account, uint256 id) external view returns (uint256); function totalSupply(uint256 id) external view returns (uint256); function mint( address recipient, uint256 qty, uint256 tokenId, uint256 fragment ) external; function burnToRedeemPilot(address account, uint256 fragment) external; function authorizedBurn(address account, uint256 tokenId) external; function tokenMintCountsByFragment(uint256 fragment, uint256 tokenId) external view returns (uint256); function addressToPilotPassClaimsByFragment(uint256 fragment, address caller) external view returns (uint256); function incrementPilotPassClaimCount( address caller, uint256 fragment, uint256 qty ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; interface IEXRInventory { function mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; error InvalidSignature(); /** * @title Coupon System * @author RacerDev * @notice Helper contract for verifying signed coupons using `ecrecover` to match the coupon signer * to the `_adminSigner` variable set during construction. * @dev The Coupon struct represents a decoded signature that was created off-chain */ contract CouponSystem { address internal _adminSigner; enum CouponType { MintPass, Pilot, Racecraft, Inventory, Reward } struct Coupon { bytes32 r; bytes32 s; uint8 v; } constructor(address signer) { _adminSigner = signer; } /** * @dev Admin can replace the admin signer address in the event the private key is compromised * @param newSigner The public key (address) of the new signer keypair */ function _replaceSigner(address newSigner) internal { _adminSigner = newSigner; } /** * @dev Accepts an already hashed set of data * @param digest The hash of the abi.encoded coupon data * @param coupon The decoded r,s,v components of the signature * @return Whether the recovered signer address matches the `_adminSigner` */ function _verifyCoupon(bytes32 digest, Coupon calldata coupon) internal view returns (bool) { address signer = ecrecover(digest, coupon.v, coupon.r, coupon.s); if (signer == address(0)) revert InvalidSignature(); return signer == _adminSigner; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @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. * * _Available since v3.1._ */ 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 `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { 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_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.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); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @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); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"adminSigner","type":"address"},{"internalType":"address","name":"trustedForwarder","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InventoryCategoryExists","type":"error"},{"inputs":[],"name":"InventoryInsufficientPassBalance","type":"error"},{"inputs":[],"name":"InventoryInvalidCoupon","type":"error"},{"inputs":[],"name":"InventoryReusedSeed","type":"error"},{"inputs":[],"name":"InventoryZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"AdminSignerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"category","type":"uint256"}],"name":"InventoryCategoryAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"category","type":"uint8"}],"name":"InventoryCategoryDoesNotExist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"category","type":"uint8"}],"name":"InventoryCategoryRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"InventoryItemsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"qty","type":"uint256"}],"name":"InventoryRewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"}],"name":"InventoryUpdateInventoryInterface","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"}],"name":"InventoryUpdateMintpassInterface","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SYS_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"categoryId","type":"uint8"},{"internalType":"uint8[9]","name":"ids","type":"uint8[9]"}],"name":"addCategory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"seed","type":"bytes32"},{"internalType":"uint256","name":"qty","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct CouponSystem.Coupon","name":"coupon","type":"tuple"}],"name":"burnToRedeemInventoryItems","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"categories","outputs":[{"internalType":"uint8","name":"exists","type":"uint8"},{"internalType":"uint8","name":"id","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"seed","type":"bytes32"},{"internalType":"uint256","name":"qty","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"internalType":"struct CouponSystem.Coupon","name":"coupon","type":"tuple"}],"name":"claimRewardItems","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"}],"name":"getCategory","outputs":[{"components":[{"internalType":"uint8","name":"exists","type":"uint8"},{"internalType":"uint8","name":"id","type":"uint8"},{"internalType":"uint8[9]","name":"tokenIds","type":"uint8[9]"}],"internalType":"struct EXRInventoryController.Category","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":"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":[],"name":"inventoryContract","outputs":[{"internalType":"contract IEXRInventory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inventoryPassId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintpassContract","outputs":[{"internalType":"contract IEXRMintPass","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"category","type":"uint8"}],"name":"removeCategory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"inventory","type":"address"}],"name":"setInventoryContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"mintpass","type":"address"}],"name":"setMintpassContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSigner","type":"address"}],"name":"updateAdminSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"usedSeeds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b506040516200212b3803806200212b8339810160408190526200003491620001ec565b6001600160a01b038181166080526001805460ff19168155600255600380546001600160a01b03191691841691909117905562000073600033620000d3565b6200009f7f102df6c829c4ae7b33ef1bb0ebd38acf773714f0196b4f4fd4b0ade595f3daf733620000d3565b620000cb7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33620000d3565b505062000224565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000172576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556200013162000176565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006200018d6200019260201b62000fa81760201c565b905090565b6080516000906001600160a01b0316331415620001b6575060131936013560601c90565b6200018d620001cb60201b62000fcf1760201c565b3390565b80516001600160a01b0381168114620001e757600080fd5b919050565b600080604083850312156200020057600080fd5b6200020b83620001cf565b91506200021b60208401620001cf565b90509250929050565b608051611eeb6200024060003960006107720152611eeb6000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c806372a7a079116100de578063c6cdbe5e11610097578063e63ab1e911610071578063e63ab1e914610378578063ef614ba31461039f578063f3052d26146103b2578063f306ba30146103d257600080fd5b8063c6cdbe5e14610325578063c766731e14610352578063d547741f1461036557600080fd5b806372a7a079146102b95780638420d576146102cc5780638456cb59146102df57806391d14854146102e75780639ada7807146102fa578063a217fddf1461031d57600080fd5b80633f4ba83a1161014b5780635c975abb116101255780635c975abb1461028057806361c6b87f1461028b5780636bd984ed146102935780637232af2b146102a657600080fd5b80633f4ba83a14610252578063560796371461025a578063572b6c051461026d57600080fd5b806301ffc9a7146101935780630cc10cd9146101bb578063248a9ca3146101d05780632f2ff15d1461020157806336568abe146102145780633f06a3e214610227575b600080fd5b6101a66101a136600461197b565b6103e7565b60405190151581526020015b60405180910390f35b6101ce6101c93660046119bb565b61041e565b005b6101f36101de3660046119d6565b60009081526020819052604090206001015490565b6040519081526020016101b2565b6101ce61020f366004611a06565b6105e5565b6101ce610222366004611a06565b61060d565b60065461023a906001600160a01b031681565b6040516001600160a01b0390911681526020016101b2565b6101ce6106a0565b6101ce610268366004611a32565b6106d8565b6101a661027b366004611a32565b610770565b60015460ff166101a6565b6101f3600381565b6101ce6102a1366004611a4d565b6107a2565b6101ce6102b4366004611a8a565b6108f9565b6101ce6102c7366004611a8a565b610b8d565b60075461023a906001600160a01b031681565b6101ce610d41565b6101a66102f5366004611a06565b610d76565b6101a66103083660046119d6565b60046020526000908152604090205460ff1681565b6101f3600081565b6103386103333660046119d6565b610d9f565b6040805160ff9384168152929091166020830152016101b2565b6101ce610360366004611a32565b610dd1565b6101ce610373366004611a06565b610e40565b6101f37f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6101ce6103ad366004611a32565b610e68565b6103c56103c03660046119d6565b610ef8565b6040516101b29190611acb565b6101f3600080516020611e9683398151915281565b60006001600160e01b03198216637965db0b60e01b148061041857506301ffc9a760e01b6001600160e01b03198316145b92915050565b600080516020611e9683398151915261043e81610439610fd3565b610fdd565b6000805b6005548110156105a2578360ff166005828154811061046357610463611b1e565b6000918252602090912060029091020154610100900460ff161415610590576005805461049290600190611b4a565b815481106104a2576104a2611b1e565b9060005260206000209060020201600582815481106104c3576104c3611b1e565b600091825260209091208254600290920201805460ff92831660ff19821681178355845461ffff1990921617610100918290049093160291909117815561051260018083019084016009611852565b50905050600580548061052757610527611b61565b600082815260208120600260001990930192830201805461ffff1916815560018101829055905050905560405160ff85168152600192507fb39116d8d44bdb1ff64dd16d2c0a1adfd1e6ba840a28a5b9c63f6a396cce06a49060200160405180910390a16105a2565b8061059a81611b77565b915050610442565b50806105e05760405160ff841681527f68e0e4796cab5ebfa4efc9e0059d489d93d2c83c0d81d891584e9b71f67c5203906020015b60405180910390a15b505050565b60008281526020819052604090206001015461060381610439610fd3565b6105e08383611041565b610615610fd3565b6001600160a01b0316816001600160a01b0316146106925760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b61069c82826110c6565b5050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6106cd81610439610fd3565b6106d5611149565b50565b600080516020611e968339815191526106f381610439610fd3565b6001600160a01b03821661071a57604051630644147560e51b815260040160405180910390fd5b600780546001600160a01b0319166001600160a01b0384169081179091556040519081527f67e491ea6e2e53efdb6f48228ff087fa213846fd3ca860f655d7d6a2da22e797906020015b60405180910390a15050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b600080516020611e968339815191526107bd81610439610fd3565b60005b60055481101561082b578360ff16600582815481106107e1576107e1611b1e565b6000918252602090912060029091020154610100900460ff161415610819576040516328f9b9a560e21b815260040160405180910390fd5b8061082381611b77565b9150506107c0565b50604080516060810182526001815260ff8516602082015281516101208181018452600593830191908690600990839083908082843760009201829052509290935250835460018181018655948252602091829020845160029092020180549285015160ff9081166101000261ffff199094169216919091179190911781556040830151929390926108c39250908301906009611895565b505060405160ff851681527fa9b387aab027a4a8a9c654dcfd48fbea1388767bd9f89713884176f84f88793c91506020016105d7565b60015460ff161561091c5760405162461bcd60e51b815260040161068990611b92565b60028054141561096e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610689565b6002805561097b33610770565b8061098557503332145b6109a15760405162461bcd60e51b815260040161068990611bbc565b6006546001600160a01b031662fdd58e6109b9610fd3565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526003602482015260440160206040518083038186803b1580156109ff57600080fd5b505afa158015610a13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a379190611c06565b610a545760405163fe64a11760e01b815260040160405180910390fd5b60008381526004602052604090205460ff1615610a8457604051636a64855560e01b815260040160405180910390fd5b6000838152600460205260408120805460ff19166001179055304660038587610aab610fd3565b604051602001610ac096959493929190611c1f565b604051602081830303815290604052805190602001209050610ae281836111e2565b610aff576040516369af28a960e01b815260040160405180910390fd5b6006546001600160a01b031663c4b53e74610b18610fd3565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260036024820152604401600060405180830381600087803b158015610b6057600080fd5b505af1158015610b74573d6000803e3d6000fd5b50505050610b828484611296565b505060016002555050565b60015460ff1615610bb05760405162461bcd60e51b815260040161068990611b92565b600280541415610c025760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610689565b60028055610c0f33610770565b80610c1957503332145b610c355760405162461bcd60e51b815260040161068990611bbc565b60008381526004602052604090205460ff1615610c6557604051636a64855560e01b815260040160405180910390fd5b60008381526004602081905260408220805460ff19166001179055309046908587610c8e610fd3565b604051602001610ca396959493929190611c1f565b604051602081830303815290604052805190602001209050610cc581836111e2565b610ce2576040516369af28a960e01b815260040160405180910390fd5b610cec8484611296565b610cf4610fd3565b6001600160a01b03167f8f0b82741e01d1711f43dff561f5182ef286b25593dd5c1576964d4a8c01c34f84604051610d2e91815260200190565b60405180910390a2505060016002555050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610d6e81610439610fd3565b6106d56114ec565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60058181548110610daf57600080fd5b600091825260209091206002909102015460ff80821692506101009091041682565b600080516020611e96833981519152610dec81610439610fd3565b600380546001600160a01b0319166001600160a01b0384161790556040516001600160a01b03831681527fc49bbf07b3ce68dc7d166375db001715e20a2cda26fae8a41ddbf7a72dadc3d190602001610764565b600082815260208190526040902060010154610e5e81610439610fd3565b6105e083836110c6565b600080516020611e96833981519152610e8381610439610fd3565b6001600160a01b038216610eaa57604051630644147560e51b815260040160405180910390fd5b600680546001600160a01b0319166001600160a01b0384169081179091556040519081527f6d3dd296d70b3c061f775b469376dc4995e3bf3d83fcee33511e806984bbf0a790602001610764565b610f00611923565b60058281548110610f1357610f13611b1e565b6000918252602091829020604080516060810182526002909302909101805460ff80821685526101009091041693830193909352805161012081018252919291908301906001830160098282826020028201916000905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411610f6a5790505050505050815250509050919050565b6000610fb333610770565b15610fc5575060131936013560601c90565b503390565b905090565b3390565b6000610fca610fa8565b610fe78282610d76565b61069c57610fff816001600160a01b03166014611544565b61100a836020611544565b60405160200161101b929190611cac565b60408051601f198184030181529082905262461bcd60e51b825261068991600401611d21565b61104b8282610d76565b61069c576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055611082610fd3565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6110d08282610d76565b1561069c576000828152602081815260408083206001600160a01b03851684529091529020805460ff19169055611105610fd3565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b60015460ff166111925760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610689565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6111c5610fd3565b6040516001600160a01b03909116815260200160405180910390a1565b6000806001846111f860608601604087016119bb565b604080516000815260208181018084529490945260ff909216908201528535606082015290850135608082015260a0016020604051602081039080840390855afa15801561124a573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661127e57604051638baa579f60e01b815260040160405180910390fd5b6003546001600160a01b039081169116149392505050565b60008167ffffffffffffffff8111156112b1576112b1611d54565b6040519080825280602002602001820160405280156112da578160200160208202803683370190505b50905060008267ffffffffffffffff8111156112f8576112f8611d54565b604051908082528060200260200182016040528015611321578160200160208202803683370190505b50905060005b8381101561144157600554600090611340906064611d6a565b8661134c600143611b4a565b6040805160208101939093529040908201524860608201526080810184905260a0016040516020818303038152906040528051906020012060001c6113919190611d89565b61139c906001611dab565b90506000805b6005548110156113ec576113b7816001611dab565b6113c2906064611d6a565b8310156113da576113d383826116e7565b91506113ec565b806113e481611b77565b9150506113a2565b508085848151811061140057611400611b1e565b602002602001018181525050600184848151811061142057611420611b1e565b6020026020010181815250505050808061143990611b77565b915050611327565b506007546001600160a01b0316631f7fdffa61145b610fd3565b84846040518463ffffffff1660e01b815260040161147b93929190611dfe565b600060405180830381600087803b15801561149557600080fd5b505af11580156114a9573d6000803e3d6000fd5b505050507f648bdc0c17de611c2baf1c098094156f94a47d553ff5b61d4e91dba5c713cfd682826040516114de929190611e50565b60405180910390a150505050565b60015460ff161561150f5760405162461bcd60e51b815260040161068990611b92565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586111c5610fd3565b60606000611553836002611d6a565b61155e906002611dab565b67ffffffffffffffff81111561157657611576611d54565b6040519080825280601f01601f1916602001820160405280156115a0576020820181803683370190505b509050600360fc1b816000815181106115bb576115bb611b1e565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106115ea576115ea611b1e565b60200101906001600160f81b031916908160001a905350600061160e846002611d6a565b611619906001611dab565b90505b6001811115611691576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061164d5761164d611b1e565b1a60f81b82828151811061166357611663611b1e565b60200101906001600160f81b031916908160001a90535060049490941c9361168a81611e7e565b905061161c565b5083156116e05760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610689565b9392505050565b600080610bb88484604051602001611709929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c61172c9190611d89565b611737906001611dab565b905060006005848154811061174e5761174e611b1e565b6000918252602082206040805161012081019182905293600290930290910160010191600991908390855b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411611779579050505050505090506109c48211156117cd578060005b602002015160ff1692505050610418565b6107d08211156117df578060016117bc565b6105dc8211156117f1578060026117bc565b61047e821115611803578060036117bc565b610320821115611815578060046117bc565b6101c2821115611827578060056117bc565b61012c821115611839578060066117bc565b609682111561184a578060076117bc565b8060086117bc565b6001830191839082156118855791601f016020900482015b8281111561188557825482559160010191906001019061186a565b50611891929150611947565b5090565b6001830191839082156118855791602002820160005b838211156118e957835183826101000a81548160ff021916908360ff16021790555092602001926001016020816000010492830192600103026118ab565b80156119165782816101000a81549060ff02191690556001016020816000010492830192600103026118e9565b5050611891929150611947565b604080516060810182526000808252602082015290810161194261195c565b905290565b5b808211156118915760008155600101611948565b6040518061012001604052806009906020820280368337509192915050565b60006020828403121561198d57600080fd5b81356001600160e01b0319811681146116e057600080fd5b803560ff811681146119b657600080fd5b919050565b6000602082840312156119cd57600080fd5b6116e0826119a5565b6000602082840312156119e857600080fd5b5035919050565b80356001600160a01b03811681146119b657600080fd5b60008060408385031215611a1957600080fd5b82359150611a29602084016119ef565b90509250929050565b600060208284031215611a4457600080fd5b6116e0826119ef565b600080610140808486031215611a6257600080fd5b611a6b846119a5565b9250848185011115611a7c57600080fd5b506020830190509250929050565b600080600083850360a0811215611aa057600080fd5b84359350602085013592506060603f1982011215611abd57600080fd5b506040840190509250925092565b60006101608201905060ff80845116835260208181860151168185015260408501516040850160005b6009811015611b13578251851682529183019190830190600101611af4565b505050505092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015611b5c57611b5c611b34565b500390565b634e487b7160e01b600052603160045260246000fd5b6000600019821415611b8b57611b8b611b34565b5060010190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252602a908201527f4e6f6e2d7472757374656420666f7277617264657220636f6e7472616374206e6040820152691bdd08185b1b1bddd95960b21b606082015260800190565b600060208284031215611c1857600080fd5b5051919050565b6001600160a01b0387811682526020820187905260c082019060058710611c5657634e487b7160e01b600052602160045260246000fd5b86604084015285606084015284608084015280841660a084015250979650505050505050565b60005b83811015611c97578181015183820152602001611c7f565b83811115611ca6576000848401525b50505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611ce4816017850160208801611c7c565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351611d15816028840160208801611c7c565b01602801949350505050565b6020815260008251806020840152611d40816040850160208701611c7c565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b6000816000190483118215151615611d8457611d84611b34565b500290565b600082611da657634e487b7160e01b600052601260045260246000fd5b500690565b60008219821115611dbe57611dbe611b34565b500190565b600081518084526020808501945080840160005b83811015611df357815187529582019590820190600101611dd7565b509495945050505050565b6001600160a01b0384168152608060208201819052600090611e2290830185611dc3565b8281036040840152611e348185611dc3565b8381036060909401939093525050600081526020019392505050565b604081526000611e636040830185611dc3565b8281036020840152611e758185611dc3565b95945050505050565b600081611e8d57611e8d611b34565b50600019019056fe102df6c829c4ae7b33ef1bb0ebd38acf773714f0196b4f4fd4b0ade595f3daf7a2646970667358221220c8a4e6ce82f938f3bc6ea68ba6968010a17a17a25223fb3c20fe77187b1ed50764736f6c63430008090033000000000000000000000000b356db9e01423ef36ad1ff23bce043b432f81d790000000000000000000000003d08ce1f9609bb02f47192ff620634d9eb0e7b56
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b356db9e01423ef36ad1ff23bce043b432f81d790000000000000000000000003d08ce1f9609bb02f47192ff620634d9eb0e7b56
-----Decoded View---------------
Arg [0] : adminSigner (address): 0xb356db9e01423ef36ad1ff23bce043b432f81d79
Arg [1] : trustedForwarder (address): 0x3d08ce1f9609bb02f47192ff620634d9eb0e7b56
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000b356db9e01423ef36ad1ff23bce043b432f81d79
Arg [1] : 0000000000000000000000003d08ce1f9609bb02f47192ff620634d9eb0e7b56
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.