Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 55 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Rescue | 6540284 | 550 days ago | IN | 0 ETH | 0.00000002 | ||||
| Rescue | 6540058 | 550 days ago | IN | 0 ETH | 0.00000003 | ||||
| Pause | 6539969 | 550 days ago | IN | 0 ETH | 0.00000003 | ||||
| Lock | 6496198 | 551 days ago | IN | 0 ETH | 0.00000019 | ||||
| Lock | 6321955 | 555 days ago | IN | 0 ETH | 0.00000014 | ||||
| Lock | 6315458 | 556 days ago | IN | 0 ETH | 0.00000014 | ||||
| Lock | 6306723 | 556 days ago | IN | 0 ETH | 0.00000003 | ||||
| Lock | 6196488 | 558 days ago | IN | 0 ETH | 0.00000038 | ||||
| Lock | 5714331 | 569 days ago | IN | 0 ETH | 0.00000014 | ||||
| Lock | 5705697 | 570 days ago | IN | 0 ETH | 0.00000029 | ||||
| Lock | 5693352 | 570 days ago | IN | 0 ETH | 0.00000163 | ||||
| Lock | 5668355 | 571 days ago | IN | 0 ETH | 0.00000007 | ||||
| Lock | 5664532 | 571 days ago | IN | 0 ETH | 0.00000003 | ||||
| Lock | 5535654 | 574 days ago | IN | 0 ETH | 0.00000017 | ||||
| Lock | 5492947 | 575 days ago | IN | 0 ETH | 0.00000135 | ||||
| Lock | 5483227 | 575 days ago | IN | 0 ETH | 0.00000207 | ||||
| Lock | 5373835 | 577 days ago | IN | 0 ETH | 0.00000211 | ||||
| Lock | 5371220 | 577 days ago | IN | 0 ETH | 0.00000189 | ||||
| Lock | 5368012 | 577 days ago | IN | 0 ETH | 0.0000018 | ||||
| Lock | 5330640 | 578 days ago | IN | 0 ETH | 0.00000184 | ||||
| Lock | 5324116 | 578 days ago | IN | 0 ETH | 0.0000041 | ||||
| Lock | 5312235 | 579 days ago | IN | 0 ETH | 0.00001313 | ||||
| Lock | 5147779 | 583 days ago | IN | 0 ETH | 0.00000349 | ||||
| Lock | 5047395 | 585 days ago | IN | 0 ETH | 0.00005064 | ||||
| Lock | 5047373 | 585 days ago | IN | 0 ETH | 0.00005342 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
StGlory
Compiler Version
v0.8.20+commit.a1b79de6
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.20;
import { OwnableRoles } from "@solady/src/auth/OwnableRoles.sol";
import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol";
import { AccessRoles } from "./access/AccessRoles.sol";
import { IStGlory } from "./interfaces/IStGlory.sol";
import { IBlast } from "./interfaces/IBlast.sol";
import { IGlory } from "./interfaces/IGlory.sol";
/**
* @title StGlory
* @notice This contract handles all functionality relating to stGLORY.
*/
contract StGlory is IStGlory, OwnableRoles, ERC20Burnable, Pausable {
uint256 private constant _BASE_MULTIPLIER = 100;
IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002);
IGlory public immutable glory;
mapping(address account => UserStake[] stakes) private _userStakes;
mapping(address account => uint256 amount) public staked;
mapping(address account => uint256 amount) public points;
mapping(uint256 duration => uint256 multiplier) public lockupMultiplier;
constructor(address _gameMaster, address _glory, address _blastGovernor) ERC20("Staked Glory", "stGLORY") {
if (_gameMaster == address(0) || _glory == address(0) || _blastGovernor == address(0)) revert ZeroAddress();
BLAST.configureClaimableGas();
BLAST.configureGovernor({ _governor: _blastGovernor });
_initializeOwner({ newOwner: msg.sender });
_grantRoles({ user: _gameMaster, roles: AccessRoles.GAME_MASTER_ROLE });
glory = IGlory(_glory);
lockupMultiplier[60 days] = 105;
lockupMultiplier[90 days] = 115;
lockupMultiplier[180 days] = 130;
lockupMultiplier[270 days] = 150;
lockupMultiplier[360 days] = 200;
}
/**
* @inheritdoc IStGlory
*/
function lock(uint256 amount, uint256 duration) external whenNotPaused {
if (amount == 0) revert InvalidAmount();
if (lockupMultiplier[duration] == 0) revert InvalidLockup();
staked[msg.sender] += amount;
_userStakes[msg.sender].push(UserStake({ amount: amount, duration: duration, startTime: block.timestamp }));
glory.transferFrom({ from: msg.sender, to: address(this), value: amount });
_mint({ account: msg.sender, value: amount });
emit Locked({ account: msg.sender, amount: amount });
}
/**
* @inheritdoc IStGlory
*/
function unlock(uint256 idx) external whenNotPaused {
uint256 len = _userStakes[msg.sender].length;
if (len == 0) revert NoStakes();
uint256 lastIdx = len - 1;
if (idx > lastIdx) revert OutOfBounds();
UserStake memory stake = _userStakes[msg.sender][idx];
if (len != 1) {
_userStakes[msg.sender][idx] = _userStakes[msg.sender][lastIdx];
}
_userStakes[msg.sender].pop();
if (block.timestamp < stake.startTime + stake.duration) revert StillLocked();
staked[msg.sender] -= stake.amount;
uint256 rewardPoints = stake.amount * stake.duration * lockupMultiplier[stake.duration] / _BASE_MULTIPLIER;
points[msg.sender] += rewardPoints;
_burn({ account: msg.sender, value: stake.amount });
glory.transfer({ to: msg.sender, value: stake.amount });
emit Unlocked({ account: msg.sender, amount: stake.amount, reward: rewardPoints });
}
/**
* @inheritdoc IStGlory
*/
function setMultiplier(uint256 duration, uint256 newMultiplier) external onlyRoles(AccessRoles.GAME_MASTER_ROLE) {
if (newMultiplier <= _BASE_MULTIPLIER) revert InvalidMultiplier();
uint256 oldMultiplier = lockupMultiplier[duration];
lockupMultiplier[duration] = newMultiplier;
emit MultiplierUpdated(duration, oldMultiplier, newMultiplier);
}
/**
* @inheritdoc IStGlory
*/
function rescue(address receiver, uint256 amount) external onlyRoles(AccessRoles.GAME_MASTER_ROLE) {
if (receiver == address(0)) revert ZeroAddress();
if (amount == 0) revert InvalidAmount();
glory.transfer({ to: receiver, value: amount });
}
/**
* @inheritdoc IStGlory
*/
function pause() external onlyRoles(AccessRoles.GAME_MASTER_ROLE) {
_pause();
}
/**
* @inheritdoc IStGlory
*/
function unpause() external onlyRoles(AccessRoles.GAME_MASTER_ROLE) {
_unpause();
}
/**
* @inheritdoc IStGlory
*/
function userStakes(address account) external view returns (UserStake[] memory) {
return _userStakes[account];
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC20 OVERRIDE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
function _update(address from, address to, uint256 value) internal override {
if (from != address(0) && to != address(0)) revert Soulbound();
super._update(from, to, value);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {Ownable} from "./Ownable.sol";
/// @notice Simple single owner and multiroles authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
/// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173)
/// for compatibility, the nomenclature for the 2-step ownership handover and roles
/// may be unique to this codebase.
abstract contract OwnableRoles is Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The `user`'s roles is updated to `roles`.
/// Each bit of `roles` represents whether the role is set.
event RolesUpdated(address indexed user, uint256 indexed roles);
/// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`.
uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE =
0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The role slot of `user` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED))
/// let roleSlot := keccak256(0x00, 0x20)
/// ```
/// This automatically ignores the upper bits of the `user` in case
/// they are not clean, as well as keep the `keccak256` under 32-bytes.
///
/// Note: This is equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`.
uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Overwrite the roles directly without authorization guard.
function _setRoles(address user, uint256 roles) internal virtual {
/// @solidity memory-safe-assembly
assembly {
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
// Store the new value.
sstore(keccak256(0x0c, 0x20), roles)
// Emit the {RolesUpdated} event.
log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles)
}
}
/// @dev Updates the roles directly without authorization guard.
/// If `on` is true, each set bit of `roles` will be turned on,
/// otherwise, each set bit of `roles` will be turned off.
function _updateRoles(address user, uint256 roles, bool on) internal virtual {
/// @solidity memory-safe-assembly
assembly {
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
let roleSlot := keccak256(0x0c, 0x20)
// Load the current value.
let current := sload(roleSlot)
// Compute the updated roles if `on` is true.
let updated := or(current, roles)
// Compute the updated roles if `on` is false.
// Use `and` to compute the intersection of `current` and `roles`,
// `xor` it with `current` to flip the bits in the intersection.
if iszero(on) { updated := xor(current, and(current, roles)) }
// Then, store the new value.
sstore(roleSlot, updated)
// Emit the {RolesUpdated} event.
log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated)
}
}
/// @dev Grants the roles directly without authorization guard.
/// Each bit of `roles` represents the role to turn on.
function _grantRoles(address user, uint256 roles) internal virtual {
_updateRoles(user, roles, true);
}
/// @dev Removes the roles directly without authorization guard.
/// Each bit of `roles` represents the role to turn off.
function _removeRoles(address user, uint256 roles) internal virtual {
_updateRoles(user, roles, false);
}
/// @dev Throws if the sender does not have any of the `roles`.
function _checkRoles(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Throws if the sender is not the owner,
/// and does not have any of the `roles`.
/// Checks for ownership first, then lazily checks for roles.
function _checkOwnerOrRoles(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner.
// Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Throws if the sender does not have any of the `roles`,
/// and is not the owner.
/// Checks for roles first, then lazily checks for ownership.
function _checkRolesOrOwner(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
// If the caller is not the stored owner.
// Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`.
/// This is meant for frontends like Etherscan, and is therefore not fully optimized.
/// Not recommended to be called on-chain.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) {
/// @solidity memory-safe-assembly
assembly {
for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } {
// We don't need to mask the values of `ordinals`, as Solidity
// cleans dirty upper bits when storing variables into memory.
roles := or(shl(mload(add(ordinals, i)), 1), roles)
}
}
}
/// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap.
/// This is meant for frontends like Etherscan, and is therefore not fully optimized.
/// Not recommended to be called on-chain.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) {
/// @solidity memory-safe-assembly
assembly {
// Grab the pointer to the free memory.
ordinals := mload(0x40)
let ptr := add(ordinals, 0x20)
let o := 0
// The absence of lookup tables, De Bruijn, etc., here is intentional for
// smaller bytecode, as this function is not meant to be called on-chain.
for { let t := roles } 1 {} {
mstore(ptr, o)
// `shr` 5 is equivalent to multiplying by 0x20.
// Push back into the ordinals array if the bit is set.
ptr := add(ptr, shl(5, and(t, 1)))
o := add(o, 1)
t := shr(o, roles)
if iszero(t) { break }
}
// Store the length of `ordinals`.
mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20))))
// Allocate the memory.
mstore(0x40, ptr)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to grant `user` `roles`.
/// If the `user` already has a role, then it will be an no-op for the role.
function grantRoles(address user, uint256 roles) public payable virtual onlyOwner {
_grantRoles(user, roles);
}
/// @dev Allows the owner to remove `user` `roles`.
/// If the `user` does not have a role, then it will be an no-op for the role.
function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner {
_removeRoles(user, roles);
}
/// @dev Allow the caller to remove their own roles.
/// If the caller does not have a role, then it will be an no-op for the role.
function renounceRoles(uint256 roles) public payable virtual {
_removeRoles(msg.sender, roles);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the roles of `user`.
function rolesOf(address user) public view virtual returns (uint256 roles) {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
// Load the stored value.
roles := sload(keccak256(0x0c, 0x20))
}
}
/// @dev Returns whether `user` has any of `roles`.
function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) {
return rolesOf(user) & roles != 0;
}
/// @dev Returns whether `user` has all of `roles`.
function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) {
return rolesOf(user) & roles == roles;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by an account with `roles`.
modifier onlyRoles(uint256 roles) virtual {
_checkRoles(roles);
_;
}
/// @dev Marks a function as only callable by the owner or by an account
/// with `roles`. Checks for ownership first, then lazily checks for roles.
modifier onlyOwnerOrRoles(uint256 roles) virtual {
_checkOwnerOrRoles(roles);
_;
}
/// @dev Marks a function as only callable by an account with `roles`
/// or the owner. Checks for roles first, then lazily checks for ownership.
modifier onlyRolesOrOwner(uint256 roles) virtual {
_checkRolesOrOwner(roles);
_;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ROLE CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// IYKYK
uint256 internal constant _ROLE_0 = 1 << 0;
uint256 internal constant _ROLE_1 = 1 << 1;
uint256 internal constant _ROLE_2 = 1 << 2;
uint256 internal constant _ROLE_3 = 1 << 3;
uint256 internal constant _ROLE_4 = 1 << 4;
uint256 internal constant _ROLE_5 = 1 << 5;
uint256 internal constant _ROLE_6 = 1 << 6;
uint256 internal constant _ROLE_7 = 1 << 7;
uint256 internal constant _ROLE_8 = 1 << 8;
uint256 internal constant _ROLE_9 = 1 << 9;
uint256 internal constant _ROLE_10 = 1 << 10;
uint256 internal constant _ROLE_11 = 1 << 11;
uint256 internal constant _ROLE_12 = 1 << 12;
uint256 internal constant _ROLE_13 = 1 << 13;
uint256 internal constant _ROLE_14 = 1 << 14;
uint256 internal constant _ROLE_15 = 1 << 15;
uint256 internal constant _ROLE_16 = 1 << 16;
uint256 internal constant _ROLE_17 = 1 << 17;
uint256 internal constant _ROLE_18 = 1 << 18;
uint256 internal constant _ROLE_19 = 1 << 19;
uint256 internal constant _ROLE_20 = 1 << 20;
uint256 internal constant _ROLE_21 = 1 << 21;
uint256 internal constant _ROLE_22 = 1 << 22;
uint256 internal constant _ROLE_23 = 1 << 23;
uint256 internal constant _ROLE_24 = 1 << 24;
uint256 internal constant _ROLE_25 = 1 << 25;
uint256 internal constant _ROLE_26 = 1 << 26;
uint256 internal constant _ROLE_27 = 1 << 27;
uint256 internal constant _ROLE_28 = 1 << 28;
uint256 internal constant _ROLE_29 = 1 << 29;
uint256 internal constant _ROLE_30 = 1 << 30;
uint256 internal constant _ROLE_31 = 1 << 31;
uint256 internal constant _ROLE_32 = 1 << 32;
uint256 internal constant _ROLE_33 = 1 << 33;
uint256 internal constant _ROLE_34 = 1 << 34;
uint256 internal constant _ROLE_35 = 1 << 35;
uint256 internal constant _ROLE_36 = 1 << 36;
uint256 internal constant _ROLE_37 = 1 << 37;
uint256 internal constant _ROLE_38 = 1 << 38;
uint256 internal constant _ROLE_39 = 1 << 39;
uint256 internal constant _ROLE_40 = 1 << 40;
uint256 internal constant _ROLE_41 = 1 << 41;
uint256 internal constant _ROLE_42 = 1 << 42;
uint256 internal constant _ROLE_43 = 1 << 43;
uint256 internal constant _ROLE_44 = 1 << 44;
uint256 internal constant _ROLE_45 = 1 << 45;
uint256 internal constant _ROLE_46 = 1 << 46;
uint256 internal constant _ROLE_47 = 1 << 47;
uint256 internal constant _ROLE_48 = 1 << 48;
uint256 internal constant _ROLE_49 = 1 << 49;
uint256 internal constant _ROLE_50 = 1 << 50;
uint256 internal constant _ROLE_51 = 1 << 51;
uint256 internal constant _ROLE_52 = 1 << 52;
uint256 internal constant _ROLE_53 = 1 << 53;
uint256 internal constant _ROLE_54 = 1 << 54;
uint256 internal constant _ROLE_55 = 1 << 55;
uint256 internal constant _ROLE_56 = 1 << 56;
uint256 internal constant _ROLE_57 = 1 << 57;
uint256 internal constant _ROLE_58 = 1 << 58;
uint256 internal constant _ROLE_59 = 1 << 59;
uint256 internal constant _ROLE_60 = 1 << 60;
uint256 internal constant _ROLE_61 = 1 << 61;
uint256 internal constant _ROLE_62 = 1 << 62;
uint256 internal constant _ROLE_63 = 1 << 63;
uint256 internal constant _ROLE_64 = 1 << 64;
uint256 internal constant _ROLE_65 = 1 << 65;
uint256 internal constant _ROLE_66 = 1 << 66;
uint256 internal constant _ROLE_67 = 1 << 67;
uint256 internal constant _ROLE_68 = 1 << 68;
uint256 internal constant _ROLE_69 = 1 << 69;
uint256 internal constant _ROLE_70 = 1 << 70;
uint256 internal constant _ROLE_71 = 1 << 71;
uint256 internal constant _ROLE_72 = 1 << 72;
uint256 internal constant _ROLE_73 = 1 << 73;
uint256 internal constant _ROLE_74 = 1 << 74;
uint256 internal constant _ROLE_75 = 1 << 75;
uint256 internal constant _ROLE_76 = 1 << 76;
uint256 internal constant _ROLE_77 = 1 << 77;
uint256 internal constant _ROLE_78 = 1 << 78;
uint256 internal constant _ROLE_79 = 1 << 79;
uint256 internal constant _ROLE_80 = 1 << 80;
uint256 internal constant _ROLE_81 = 1 << 81;
uint256 internal constant _ROLE_82 = 1 << 82;
uint256 internal constant _ROLE_83 = 1 << 83;
uint256 internal constant _ROLE_84 = 1 << 84;
uint256 internal constant _ROLE_85 = 1 << 85;
uint256 internal constant _ROLE_86 = 1 << 86;
uint256 internal constant _ROLE_87 = 1 << 87;
uint256 internal constant _ROLE_88 = 1 << 88;
uint256 internal constant _ROLE_89 = 1 << 89;
uint256 internal constant _ROLE_90 = 1 << 90;
uint256 internal constant _ROLE_91 = 1 << 91;
uint256 internal constant _ROLE_92 = 1 << 92;
uint256 internal constant _ROLE_93 = 1 << 93;
uint256 internal constant _ROLE_94 = 1 << 94;
uint256 internal constant _ROLE_95 = 1 << 95;
uint256 internal constant _ROLE_96 = 1 << 96;
uint256 internal constant _ROLE_97 = 1 << 97;
uint256 internal constant _ROLE_98 = 1 << 98;
uint256 internal constant _ROLE_99 = 1 << 99;
uint256 internal constant _ROLE_100 = 1 << 100;
uint256 internal constant _ROLE_101 = 1 << 101;
uint256 internal constant _ROLE_102 = 1 << 102;
uint256 internal constant _ROLE_103 = 1 << 103;
uint256 internal constant _ROLE_104 = 1 << 104;
uint256 internal constant _ROLE_105 = 1 << 105;
uint256 internal constant _ROLE_106 = 1 << 106;
uint256 internal constant _ROLE_107 = 1 << 107;
uint256 internal constant _ROLE_108 = 1 << 108;
uint256 internal constant _ROLE_109 = 1 << 109;
uint256 internal constant _ROLE_110 = 1 << 110;
uint256 internal constant _ROLE_111 = 1 << 111;
uint256 internal constant _ROLE_112 = 1 << 112;
uint256 internal constant _ROLE_113 = 1 << 113;
uint256 internal constant _ROLE_114 = 1 << 114;
uint256 internal constant _ROLE_115 = 1 << 115;
uint256 internal constant _ROLE_116 = 1 << 116;
uint256 internal constant _ROLE_117 = 1 << 117;
uint256 internal constant _ROLE_118 = 1 << 118;
uint256 internal constant _ROLE_119 = 1 << 119;
uint256 internal constant _ROLE_120 = 1 << 120;
uint256 internal constant _ROLE_121 = 1 << 121;
uint256 internal constant _ROLE_122 = 1 << 122;
uint256 internal constant _ROLE_123 = 1 << 123;
uint256 internal constant _ROLE_124 = 1 << 124;
uint256 internal constant _ROLE_125 = 1 << 125;
uint256 internal constant _ROLE_126 = 1 << 126;
uint256 internal constant _ROLE_127 = 1 << 127;
uint256 internal constant _ROLE_128 = 1 << 128;
uint256 internal constant _ROLE_129 = 1 << 129;
uint256 internal constant _ROLE_130 = 1 << 130;
uint256 internal constant _ROLE_131 = 1 << 131;
uint256 internal constant _ROLE_132 = 1 << 132;
uint256 internal constant _ROLE_133 = 1 << 133;
uint256 internal constant _ROLE_134 = 1 << 134;
uint256 internal constant _ROLE_135 = 1 << 135;
uint256 internal constant _ROLE_136 = 1 << 136;
uint256 internal constant _ROLE_137 = 1 << 137;
uint256 internal constant _ROLE_138 = 1 << 138;
uint256 internal constant _ROLE_139 = 1 << 139;
uint256 internal constant _ROLE_140 = 1 << 140;
uint256 internal constant _ROLE_141 = 1 << 141;
uint256 internal constant _ROLE_142 = 1 << 142;
uint256 internal constant _ROLE_143 = 1 << 143;
uint256 internal constant _ROLE_144 = 1 << 144;
uint256 internal constant _ROLE_145 = 1 << 145;
uint256 internal constant _ROLE_146 = 1 << 146;
uint256 internal constant _ROLE_147 = 1 << 147;
uint256 internal constant _ROLE_148 = 1 << 148;
uint256 internal constant _ROLE_149 = 1 << 149;
uint256 internal constant _ROLE_150 = 1 << 150;
uint256 internal constant _ROLE_151 = 1 << 151;
uint256 internal constant _ROLE_152 = 1 << 152;
uint256 internal constant _ROLE_153 = 1 << 153;
uint256 internal constant _ROLE_154 = 1 << 154;
uint256 internal constant _ROLE_155 = 1 << 155;
uint256 internal constant _ROLE_156 = 1 << 156;
uint256 internal constant _ROLE_157 = 1 << 157;
uint256 internal constant _ROLE_158 = 1 << 158;
uint256 internal constant _ROLE_159 = 1 << 159;
uint256 internal constant _ROLE_160 = 1 << 160;
uint256 internal constant _ROLE_161 = 1 << 161;
uint256 internal constant _ROLE_162 = 1 << 162;
uint256 internal constant _ROLE_163 = 1 << 163;
uint256 internal constant _ROLE_164 = 1 << 164;
uint256 internal constant _ROLE_165 = 1 << 165;
uint256 internal constant _ROLE_166 = 1 << 166;
uint256 internal constant _ROLE_167 = 1 << 167;
uint256 internal constant _ROLE_168 = 1 << 168;
uint256 internal constant _ROLE_169 = 1 << 169;
uint256 internal constant _ROLE_170 = 1 << 170;
uint256 internal constant _ROLE_171 = 1 << 171;
uint256 internal constant _ROLE_172 = 1 << 172;
uint256 internal constant _ROLE_173 = 1 << 173;
uint256 internal constant _ROLE_174 = 1 << 174;
uint256 internal constant _ROLE_175 = 1 << 175;
uint256 internal constant _ROLE_176 = 1 << 176;
uint256 internal constant _ROLE_177 = 1 << 177;
uint256 internal constant _ROLE_178 = 1 << 178;
uint256 internal constant _ROLE_179 = 1 << 179;
uint256 internal constant _ROLE_180 = 1 << 180;
uint256 internal constant _ROLE_181 = 1 << 181;
uint256 internal constant _ROLE_182 = 1 << 182;
uint256 internal constant _ROLE_183 = 1 << 183;
uint256 internal constant _ROLE_184 = 1 << 184;
uint256 internal constant _ROLE_185 = 1 << 185;
uint256 internal constant _ROLE_186 = 1 << 186;
uint256 internal constant _ROLE_187 = 1 << 187;
uint256 internal constant _ROLE_188 = 1 << 188;
uint256 internal constant _ROLE_189 = 1 << 189;
uint256 internal constant _ROLE_190 = 1 << 190;
uint256 internal constant _ROLE_191 = 1 << 191;
uint256 internal constant _ROLE_192 = 1 << 192;
uint256 internal constant _ROLE_193 = 1 << 193;
uint256 internal constant _ROLE_194 = 1 << 194;
uint256 internal constant _ROLE_195 = 1 << 195;
uint256 internal constant _ROLE_196 = 1 << 196;
uint256 internal constant _ROLE_197 = 1 << 197;
uint256 internal constant _ROLE_198 = 1 << 198;
uint256 internal constant _ROLE_199 = 1 << 199;
uint256 internal constant _ROLE_200 = 1 << 200;
uint256 internal constant _ROLE_201 = 1 << 201;
uint256 internal constant _ROLE_202 = 1 << 202;
uint256 internal constant _ROLE_203 = 1 << 203;
uint256 internal constant _ROLE_204 = 1 << 204;
uint256 internal constant _ROLE_205 = 1 << 205;
uint256 internal constant _ROLE_206 = 1 << 206;
uint256 internal constant _ROLE_207 = 1 << 207;
uint256 internal constant _ROLE_208 = 1 << 208;
uint256 internal constant _ROLE_209 = 1 << 209;
uint256 internal constant _ROLE_210 = 1 << 210;
uint256 internal constant _ROLE_211 = 1 << 211;
uint256 internal constant _ROLE_212 = 1 << 212;
uint256 internal constant _ROLE_213 = 1 << 213;
uint256 internal constant _ROLE_214 = 1 << 214;
uint256 internal constant _ROLE_215 = 1 << 215;
uint256 internal constant _ROLE_216 = 1 << 216;
uint256 internal constant _ROLE_217 = 1 << 217;
uint256 internal constant _ROLE_218 = 1 << 218;
uint256 internal constant _ROLE_219 = 1 << 219;
uint256 internal constant _ROLE_220 = 1 << 220;
uint256 internal constant _ROLE_221 = 1 << 221;
uint256 internal constant _ROLE_222 = 1 << 222;
uint256 internal constant _ROLE_223 = 1 << 223;
uint256 internal constant _ROLE_224 = 1 << 224;
uint256 internal constant _ROLE_225 = 1 << 225;
uint256 internal constant _ROLE_226 = 1 << 226;
uint256 internal constant _ROLE_227 = 1 << 227;
uint256 internal constant _ROLE_228 = 1 << 228;
uint256 internal constant _ROLE_229 = 1 << 229;
uint256 internal constant _ROLE_230 = 1 << 230;
uint256 internal constant _ROLE_231 = 1 << 231;
uint256 internal constant _ROLE_232 = 1 << 232;
uint256 internal constant _ROLE_233 = 1 << 233;
uint256 internal constant _ROLE_234 = 1 << 234;
uint256 internal constant _ROLE_235 = 1 << 235;
uint256 internal constant _ROLE_236 = 1 << 236;
uint256 internal constant _ROLE_237 = 1 << 237;
uint256 internal constant _ROLE_238 = 1 << 238;
uint256 internal constant _ROLE_239 = 1 << 239;
uint256 internal constant _ROLE_240 = 1 << 240;
uint256 internal constant _ROLE_241 = 1 << 241;
uint256 internal constant _ROLE_242 = 1 << 242;
uint256 internal constant _ROLE_243 = 1 << 243;
uint256 internal constant _ROLE_244 = 1 << 244;
uint256 internal constant _ROLE_245 = 1 << 245;
uint256 internal constant _ROLE_246 = 1 << 246;
uint256 internal constant _ROLE_247 = 1 << 247;
uint256 internal constant _ROLE_248 = 1 << 248;
uint256 internal constant _ROLE_249 = 1 << 249;
uint256 internal constant _ROLE_250 = 1 << 250;
uint256 internal constant _ROLE_251 = 1 << 251;
uint256 internal constant _ROLE_252 = 1 << 252;
uint256 internal constant _ROLE_253 = 1 << 253;
uint256 internal constant _ROLE_254 = 1 << 254;
uint256 internal constant _ROLE_255 = 1 << 255;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)
pragma solidity ^0.8.20;
import {ERC20} from "../ERC20.sol";
import {Context} from "../../../utils/Context.sol";
/**
* @dev Extension of {ERC20} that allows token holders to destroy both their own
* tokens and those that they have an allowance for, in a way that can be
* recognized off-chain (via event analysis).
*/
abstract contract ERC20Burnable is Context, ERC20 {
/**
* @dev Destroys a `value` amount of tokens from the caller.
*
* See {ERC20-_burn}.
*/
function burn(uint256 value) public virtual {
_burn(_msgSender(), value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, deducting from
* the caller's allowance.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for ``accounts``'s tokens of at least
* `value`.
*/
function burnFrom(address account, uint256 value) public virtual {
_spendAllowance(account, _msgSender(), value);
_burn(account, value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../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 {
bool private _paused;
/**
* @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);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @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.20;
/**
* @title AccessRoles
* @notice This library contains all the valid roles within the protocol. Roles have been defined to mimic
* {Solady.OwnableRoles} roles.
*/
library AccessRoles {
/// `OwnableRoles._ROLE_0`
uint256 public constant GAME_MASTER_ROLE = 1 << 0;
/// `OwnableRoles._ROLE_1`
uint256 public constant SEEDER_ROLE = 1 << 1;
/// `OwnableRoles._ROLE_2`
uint256 public constant MINTER_ROLE = 1 << 2;
/// `OwnableRoles._ROLE_3`
uint256 public constant RESOLVER_ROLE = 1 << 3;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
/**
* @title IStGlory
* @notice Interface for StGlory.
*/
interface IStGlory is IERC20 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Thrown when the zero address is provided as input.
*/
error ZeroAddress();
/**
* Thrown when an invalid amount is provided as input.
*/
error InvalidAmount();
/**
* Thrown when an invalid lockup duration is specified.
*/
error InvalidLockup();
/**
* Thrown when a user does not have an active stake.
*/
error NoStakes();
/**
* Thrown when an invalid index is provided.
*/
error OutOfBounds();
/**
* Thrown when a user stake has not completed yet.
*/
error StillLocked();
/**
* Thrown when an invalid multiplier is found.
*/
error InvalidMultiplier();
/**
* Thrown when attempting to transfer stGlory.
*/
error Soulbound();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STRUCTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Struct encapsulating a user stake.
* @param amount Number of tokens staked.
* @param duration Specified lockup duration.
* @param startTime Timestamp of when the tokens were locked.
*/
struct UserStake {
uint256 amount;
uint256 duration;
uint256 startTime;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Emitted when a user locks tokens.
* @param account Address of the user who has locked tokens.
* @param amount Number of tokens locked.
*/
event Locked(address indexed account, uint256 amount);
/**
* Emitted when a user unlocks tokens.
* @param account Address of the user who has unlocked tokens.
* @param amount Number of tokens locked.
* @param reward Number of points acquired.
*/
event Unlocked(address indexed account, uint256 amount, uint256 reward);
/**
* Emitted when a lockup multiplier is modified.
* @param duration Duration for the respective multiplier.
* @param oldMultiplier Old lockup multiplier.
* @param newMultiplier New lockup multiplier.
*/
event MultiplierUpdated(uint256 duration, uint256 oldMultiplier, uint256 newMultiplier);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Function used to lock tokens.
* @param amount Number of tokens to lock.
* @param duration Duration in seconds to lock tokens for.
*/
function lock(uint256 amount, uint256 duration) external;
/**
* Function used to unlock tokens.
* @param idx `UserStakes` index.
*/
function unlock(uint256 idx) external;
/**
* Function used to update staking point multipliers.
* @param duration Associated staking duration.
* @param newMultiplier New points multiplier.
*/
function setMultiplier(uint256 duration, uint256 newMultiplier) external;
/**
* Function used to rescue tokens.
* @param receiver Receiving address of the rescued tokens.
* @param amount Number of tokens to rescue.
*/
function rescue(address receiver, uint256 amount) external;
/**
* Function used to pause the contract.
*/
function pause() external;
/**
* Function used to unpause the contract.
*/
function unpause() external;
/**
* Function used to view all stakes for a given `account`.
* @param account Desired account to lookup.
*/
function userStakes(address account) external view returns (UserStake[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/**
* @title IBlast
* @notice Interface for Blast.
*/
interface IBlast {
enum YieldMode {
AUTOMATIC,
VOID,
CLAIMABLE
}
enum GasMode {
VOID,
CLAIMABLE
}
// configure
function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external;
function configure(YieldMode _yield, GasMode gasMode, address governor) external;
// base configuration options
function configureClaimableYield() external;
function configureClaimableYieldOnBehalf(address contractAddress) external;
function configureAutomaticYield() external;
function configureAutomaticYieldOnBehalf(address contractAddress) external;
function configureVoidYield() external;
function configureVoidYieldOnBehalf(address contractAddress) external;
function configureClaimableGas() external;
function configureClaimableGasOnBehalf(address contractAddress) external;
function configureVoidGas() external;
function configureVoidGasOnBehalf(address contractAddress) external;
function configureGovernor(address _governor) external;
function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external;
// claim yield
function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256);
function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256);
// claim gas
function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGasAtMinClaimRate(
address contractAddress,
address recipientOfGas,
uint256 minClaimRateBips
)
external
returns (uint256);
function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGas(
address contractAddress,
address recipientOfGas,
uint256 gasToClaim,
uint256 gasSecondsToConsume
)
external
returns (uint256);
// read functions
function readClaimableYield(address contractAddress) external view returns (uint256);
function readYieldConfiguration(address contractAddress) external view returns (uint8);
function readGasParams(address contractAddress)
external
view
returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
/**
* @title IGlory
* @notice Interface for Glory.
*/
interface IGlory is IERC20 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Thrown when the zero address is provided as input.
*/
error ZeroAddress();
/**
* Thrown when trying to enable transfers when transfers are already enabled.
*/
error TradingEnabled();
/**
* Thrown when the caller is not authorized to transfer tokens.
*/
error CallerBlocked();
/**
* Thrown when a user exceeds the maximum wallet balance of tokens.
*/
error OverMaxBalance();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* Function used to destroy `value` amount of tokens from the caller.
* @param value Amount of tokens to destroy.
*
* See {ERC20-_burn}.
*/
function burn(uint256 value) external;
/**
* Function used to destroy `value` amount of tokens from `account`, deducting from
* the caller's allowance.
*
* @param account Address to destroy tokens from.
* @param value Amount of tokens to destroy.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for `accounts`'s tokens of at least
* `value`.
*/
function burnFrom(address account, uint256 value) external;
/**
* Function used to update the mapping of addresses that can transfer tokens when transfers are disabled.
* @param account Address to modify whitelisting for.
* @param status Flag indicating if `account` can transfer tokens or not.
*/
function updateWhitelist(address account, bool status) external;
/**
* Function used to enable token transfers.
*/
function enableTransfers() external;
/**
* Function used to set a new `maxBalance` value.
* @param amount New maximum amount of tokens a user can hold.
*/
function setMaxBalance(uint256 amount) external;
/**
* Function used to toggle the check for maxiumum wallet balances.
*/
function toggleMaxBalanceCheck() external;
/**
* Function used to view if an account is whitelisted.
*/
function whitelist(address account) external view returns (bool);
/**
* Function used to set the pair address.
*/
function setPair(address pairAddr) external;
/**
* Function used to view if transfers are currently disabled.
*/
function transfersDisabled() external view returns (bool);
/**
* Function used to view if the maximum wallet limit is being enforced.
*/
function enforceMaxBalance() external view returns (bool);
/**
* Function used to view the maximum number of tokens a wallet can hold, assuming not transferred
* from a whitelisted address.
*/
function maxBalance() external view returns (uint256);
/**
* Function used to view the Thruster pair.
*/
function pair() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to call the function.
error Unauthorized();
/// @dev The `newOwner` cannot be the zero address.
error NewOwnerIsZeroAddress();
/// @dev The `pendingOwner` does not have a valid handover request.
error NoHandoverRequest();
/// @dev Cannot double-initialize.
error AlreadyInitialized();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ownership is transferred from `oldOwner` to `newOwner`.
/// This event is intentionally kept the same as OpenZeppelin's Ownable to be
/// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
/// despite it not being as lightweight as a single argument event.
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
/// @dev An ownership handover to `pendingOwner` has been requested.
event OwnershipHandoverRequested(address indexed pendingOwner);
/// @dev The ownership handover to `pendingOwner` has been canceled.
event OwnershipHandoverCanceled(address indexed pendingOwner);
/// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
/// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
/// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The owner slot is given by:
/// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
/// It is intentionally chosen to be a high value
/// to avoid collision with lower slots.
/// The choice of manual storage layout is to enable compatibility
/// with both regular and upgradeable contracts.
bytes32 internal constant _OWNER_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;
/// The ownership handover slot of `newOwner` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
/// let handoverSlot := keccak256(0x00, 0x20)
/// ```
/// It stores the expiry timestamp of the two-step ownership handover.
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
function _guardInitializeOwner() internal pure virtual returns (bool guard) {}
/// @dev Initializes the owner directly without authorization guard.
/// This function must be called upon initialization,
/// regardless of whether the contract is upgradeable or not.
/// This is to enable generalization to both regular and upgradeable contracts,
/// and to save gas in case the initial owner is not the caller.
/// For performance reasons, this function will not check if there
/// is an existing owner.
function _initializeOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
if sload(ownerSlot) {
mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
revert(0x1c, 0x04)
}
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
} else {
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(_OWNER_SLOT, newOwner)
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
}
/// @dev Sets the owner directly without authorization guard.
function _setOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
}
} else {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, newOwner)
}
}
}
/// @dev Throws if the sender is not the owner.
function _checkOwner() internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner, revert.
if iszero(eq(caller(), sload(_OWNER_SLOT))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns how long a two-step ownership handover is valid for in seconds.
/// Override to return a different value if needed.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to transfer the ownership to `newOwner`.
function transferOwnership(address newOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
/// @dev Allows the owner to renounce their ownership.
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
/// @dev Request a two-step ownership handover to the caller.
/// The request will automatically expire in 48 hours (172800 seconds) by default.
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to `expires`.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
// Emit the {OwnershipHandoverRequested} event.
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
/// @dev Cancels the two-step ownership handover to the caller, if any.
function cancelOwnershipHandover() public payable virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
// Emit the {OwnershipHandoverCanceled} event.
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
/// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
/// Reverts if there is no existing ownership handover requested by `pendingOwner`.
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
// If the handover does not exist, or has expired.
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
revert(0x1c, 0x04)
}
// Set the handover slot to 0.
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the owner of the contract.
function owner() public view virtual returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(_OWNER_SLOT)
}
}
/// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
// Compute the handover slot.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
// Load the handover slot.
result := sload(keccak256(0x0c, 0x20))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by the owner.
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @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 view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
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) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
/**
* @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 {
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply += value;
} 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 {
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
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// 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) (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) (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);
}{
"remappings": [
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@erc721a-upgradeable/=lib/ERC721A-Upgradeable/contracts/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"@openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"@openzeppelin-contracts/=lib/openzeppelin-contracts/",
"@solady/=lib/solady/",
"@v2-core/=lib/v2-core/contracts/",
"@v2-periphery/=lib/v2-periphery/contracts/",
"ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"solady/=lib/solady/",
"v2-core/=lib/v2-core/contracts/",
"v2-periphery/=lib/v2-periphery/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_gameMaster","type":"address"},{"internalType":"address","name":"_glory","type":"address"},{"internalType":"address","name":"_blastGovernor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","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":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidLockup","type":"error"},{"inputs":[],"name":"InvalidMultiplier","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NoStakes","type":"error"},{"inputs":[],"name":"OutOfBounds","type":"error"},{"inputs":[],"name":"Soulbound","type":"error"},{"inputs":[],"name":"StillLocked","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"ZeroAddress","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"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldMultiplier","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMultiplier","type":"uint256"}],"name":"MultiplierUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"RolesUpdated","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"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"Unlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"BLAST","outputs":[{"internalType":"contract IBlast","name":"","type":"address"}],"stateMutability":"view","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":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"glory","outputs":[{"internalType":"contract IGlory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAllRoles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAnyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"lockupMultiplier","outputs":[{"internalType":"uint256","name":"multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"points","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"renounceRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rolesOf","outputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"newMultiplier","type":"uint256"}],"name":"setMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"staked","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"unlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"userStakes","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"}],"internalType":"struct IStGlory.UserStake[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a06040523480156200001157600080fd5b5060405162001e2938038062001e29833981016040819052620000349162000386565b6040518060400160405280600c81526020016b5374616b656420476c6f727960a01b815250604051806040016040528060078152602001667374474c4f525960c81b81525081600390816200008a919062000475565b50600462000099828262000475565b50506005805460ff19169055506001600160a01b0383161580620000c457506001600160a01b038216155b80620000d757506001600160a01b038116155b15620000f65760405163d92e233d60e01b815260040160405180910390fd5b7343000000000000000000000000000000000000026001600160a01b0316634e606c476040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200014657600080fd5b505af11580156200015b573d6000803e3d6000fd5b5050604051631d70c8d360e31b81526001600160a01b0384166004820152734300000000000000000000000000000000000002925063eb8646989150602401600060405180830381600087803b158015620001b557600080fd5b505af1158015620001ca573d6000803e3d6000fd5b50505050620001df33620002c160201b60201c565b620001ec836001620002fd565b506001600160a01b031660805250600960205260697ffadaeb9111d7d426937b47760fa2675a2534714d6d86b7faeec753e71ba2808d5560737f1b25c710cd36f6abd0d946f0bf4d8862460476968c07544e42c0a1bbebcf00bd5560827f966c1dcd8a18560ec136a9e50a17e02db9367b367229ee43c437a3440f36d0f45560967fd038c10e39192cb326e7fe92139a30e9473c3a058683271474844e9b3feeddb6556301da9c0060005260c87f3da9ff42dc1acec014e9675ce82ac16166880cc314e9cb97a9b834a6909d59535562000541565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b6200030b828260016200030f565b5050565b638b78c6d8600c52826000526020600c2080548381178362000332575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b80516001600160a01b03811681146200038157600080fd5b919050565b6000806000606084860312156200039c57600080fd5b620003a78462000369565b9250620003b76020850162000369565b9150620003c76040850162000369565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620003fb57607f821691505b6020821081036200041c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200047057600081815260208120601f850160051c810160208610156200044b5750805b601f850160051c820191505b818110156200046c5782815560010162000457565b5050505b505050565b81516001600160401b03811115620004915762000491620003d0565b620004a981620004a28454620003e6565b8462000422565b602080601f831160018114620004e15760008415620004c85750858301515b600019600386901b1c1916600185901b1785556200046c565b600085815260208120601f198616915b828110156200051257888601518255948401946001909101908401620004f1565b5085821015620005315787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6080516118b7620005726000396000818161069d015281816108aa01528181610d6d0152610ec901526118b76000f3fe60806040526004361061021a5760003560e01c806354d1f13d116101235780638da7ad23116100ab578063dd62ed3e1161006f578063dd62ed3e14610632578063f04e283e14610678578063f188e7f61461068b578063f2fde38b146106bf578063fee81cf4146106d257600080fd5b80638da7ad231461058857806395d89b41146105b557806397d75776146105ca57806398807d84146105e5578063a9059cbb1461061257600080fd5b8063715018a6116100f2578063715018a6146104fe57806379cc6790146105065780637a4e4ecf146105265780638456cb59146105465780638da5cb5b1461055b57600080fd5b806354d1f13d146104885780635c975abb146104905780636198e339146104a857806370a08231146104c857600080fd5b806325692962116101a6578063358b816611610175578063358b8166146103dc5780633f4ba83a1461040957806342966c681461041e5780634a4ee7b11461043e578063514e62fc1461045157600080fd5b806325692962146103655780632de948071461036d578063313ce567146103a0578063333271d0146103bc57600080fd5b8063183a4f6e116101ed578063183a4f6e146102bb5780631c10893f146102ce5780631cd64df4146102e15780631f96da371461031857806323b872dd1461034557600080fd5b806306fdde031461021f578063095ea7b31461024a5780631338736f1461027a57806318160ddd1461029c575b600080fd5b34801561022b57600080fd5b50610234610705565b60405161024191906115cb565b60405180910390f35b34801561025657600080fd5b5061026a610265366004611635565b610797565b6040519015158152602001610241565b34801561028657600080fd5b5061029a61029536600461165f565b6107b1565b005b3480156102a857600080fd5b506002545b604051908152602001610241565b61029a6102c9366004611681565b61095b565b61029a6102dc366004611635565b610968565b3480156102ed57600080fd5b5061026a6102fc366004611635565b638b78c6d8600c90815260009290925260209091205481161490565b34801561032457600080fd5b506102ad610333366004611681565b60096020526000908152604090205481565b34801561035157600080fd5b5061026a61036036600461169a565b61097e565b61029a6109a2565b34801561037957600080fd5b506102ad6103883660046116d6565b638b78c6d8600c908152600091909152602090205490565b3480156103ac57600080fd5b5060405160128152602001610241565b3480156103c857600080fd5b5061029a6103d736600461165f565b6109f2565b3480156103e857600080fd5b506102ad6103f73660046116d6565b60086020526000908152604090205481565b34801561041557600080fd5b5061029a610a7a565b34801561042a57600080fd5b5061029a610439366004611681565b610a8d565b61029a61044c366004611635565b610a97565b34801561045d57600080fd5b5061026a61046c366004611635565b638b78c6d8600c90815260009290925260209091205416151590565b61029a610aa9565b34801561049c57600080fd5b5060055460ff1661026a565b3480156104b457600080fd5b5061029a6104c3366004611681565b610ae5565b3480156104d457600080fd5b506102ad6104e33660046116d6565b6001600160a01b031660009081526020819052604090205490565b61029a610e27565b34801561051257600080fd5b5061029a610521366004611635565b610e3b565b34801561053257600080fd5b5061029a610541366004611635565b610e50565b34801561055257600080fd5b5061029a610f3c565b34801561056757600080fd5b50638b78c6d819545b6040516001600160a01b039091168152602001610241565b34801561059457600080fd5b506105a86105a33660046116d6565b610f4f565b60405161024191906116f8565b3480156105c157600080fd5b50610234610fe2565b3480156105d657600080fd5b506105706002604360981b0181565b3480156105f157600080fd5b506102ad6106003660046116d6565b60076020526000908152604090205481565b34801561061e57600080fd5b5061026a61062d366004611635565b610ff1565b34801561063e57600080fd5b506102ad61064d366004611751565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b61029a6106863660046116d6565b610fff565b34801561069757600080fd5b506105707f000000000000000000000000000000000000000000000000000000000000000081565b61029a6106cd3660046116d6565b61103c565b3480156106de57600080fd5b506102ad6106ed3660046116d6565b63389a75e1600c908152600091909152602090205490565b60606003805461071490611784565b80601f016020809104026020016040519081016040528092919081815260200182805461074090611784565b801561078d5780601f106107625761010080835404028352916020019161078d565b820191906000526020600020905b81548152906001019060200180831161077057829003601f168201915b5050505050905090565b6000336107a5818585611063565b60019150505b92915050565b6107b9611075565b816000036107da5760405163162908e360e11b815260040160405180910390fd5b60008181526009602052604081205490036108085760405163f38bb1ad60e01b815260040160405180910390fd5b33600090815260076020526040812080548492906108279084906117d4565b9091555050336000818152600660209081526040808320815160608101835287815280840187815242828501908152835460018082018655948852959096209151600390950290910193845551908301559151600290910155516323b872dd60e01b81526004810191909152306024820152604481018390526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303816000875af11580156108f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091791906117e7565b506109223383611099565b60405182815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a25050565b61096533826110d4565b50565b6109706110e0565b61097a82826110fb565b5050565b60003361098c858285611107565b61099785858561117f565b506001949350505050565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b60016109fd816111de565b60648211610a1e57604051631bc4bcf760e21b815260040160405180910390fd5b60008381526009602090815260409182902080549085905582518681529182018190529181018490527f0de1269906fcaa631bbf70b295a7d636351c0e9f4fb7825498bdda2ff94ff4949060600160405180910390a150505050565b6001610a85816111de565b610965611204565b6109653382611256565b610a9f6110e0565b61097a82826110d4565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b610aed611075565b3360009081526006602052604081205490819003610b1e57604051632cdb939b60e21b815260040160405180910390fd5b6000610b2b600183611809565b905080831115610b4e57604051632d0483c560e21b815260040160405180910390fd5b336000908152600660205260408120805485908110610b6f57610b6f61181c565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905082600114610c3e57336000908152600660205260409020805483908110610bd157610bd161181c565b906000526020600020906003020160066000336001600160a01b03166001600160a01b031681526020019081526020016000208581548110610c1557610c1561181c565b600091825260209091208254600390920201908155600180830154908201556002918201549101555b336000908152600660205260409020805480610c5c57610c5c611832565b60008281526020808220600360001990940193840201828155600181018390556002019190915591558101516040820151610c9791906117d4565b421015610cb757604051636100d92960e11b815260040160405180910390fd5b80513360009081526007602052604081208054909190610cd8908490611809565b9091555050602080820180516000908152600990925260408220549051835160649291610d0491611848565b610d0e9190611848565b610d18919061185f565b33600090815260086020526040812080549293508392909190610d3c9084906117d4565b90915550508151610d4e903390611256565b815160405163a9059cbb60e01b815233600482015260248101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015610dbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de291906117e7565b508151604080519182526020820183905233917f3f2f29fa02cc34566ac167b446be0be9e0254cac18eda93b2dfe6a7a7c8affb9910160405180910390a25050505050565b610e2f6110e0565b610e39600061128c565b565b610e46823383611107565b61097a8282611256565b6001610e5b816111de565b6001600160a01b038316610e825760405163d92e233d60e01b815260040160405180910390fd5b81600003610ea35760405163162908e360e11b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3691906117e7565b50505050565b6001610f47816111de565b6109656112ca565b6001600160a01b0381166000908152600660209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610fd75783829060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505081526020019060010190610f87565b505050509050919050565b60606004805461071490611784565b6000336107a581858561117f565b6110076110e0565b63389a75e1600c52806000526020600c20805442111561102f57636f5e88186000526004601cfd5b600090556109658161128c565b6110446110e0565b8060601b61105a57637448fbae6000526004601cfd5b6109658161128c565b6110708383836001611307565b505050565b60055460ff1615610e395760405163d93c066560e01b815260040160405180910390fd5b6001600160a01b0382166110c85760405163ec442f0560e01b8152600060048201526024015b60405180910390fd5b61097a600083836113dc565b61097a82826000611425565b638b78c6d819543314610e39576382b429006000526004601cfd5b61097a82826001611425565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610f36578181101561117057604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064016110bf565b610f3684848484036000611307565b6001600160a01b0383166111a957604051634b637e8f60e11b8152600060048201526024016110bf565b6001600160a01b0382166111d35760405163ec442f0560e01b8152600060048201526024016110bf565b6110708383836113dc565b638b78c6d8600c5233600052806020600c205416610965576382b429006000526004601cfd5b61120c61147e565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b03821661128057604051634b637e8f60e11b8152600060048201526024016110bf565b61097a826000836113dc565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b6112d2611075565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586112393390565b6001600160a01b0384166113315760405163e602df0560e01b8152600060048201526024016110bf565b6001600160a01b03831661135b57604051634a1406b160e11b8152600060048201526024016110bf565b6001600160a01b0380851660009081526001602090815260408083209387168352929052208290558015610f3657826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516113ce91815260200190565b60405180910390a350505050565b6001600160a01b038316158015906113fc57506001600160a01b03821615155b1561141a5760405163a4420a9560e01b815260040160405180910390fd5b6110708383836114a1565b638b78c6d8600c52826000526020600c20805483811783611447575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b60055460ff16610e3957604051638dfc202b60e01b815260040160405180910390fd5b6001600160a01b0383166114cc5780600260008282546114c191906117d4565b9091555061153e9050565b6001600160a01b0383166000908152602081905260409020548181101561151f5760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016110bf565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b03821661155a57600280548290039055611579565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516115be91815260200190565b60405180910390a3505050565b600060208083528351808285015260005b818110156115f8578581018301518582016040015282016115dc565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461163057600080fd5b919050565b6000806040838503121561164857600080fd5b61165183611619565b946020939093013593505050565b6000806040838503121561167257600080fd5b50508035926020909101359150565b60006020828403121561169357600080fd5b5035919050565b6000806000606084860312156116af57600080fd5b6116b884611619565b92506116c660208501611619565b9150604084013590509250925092565b6000602082840312156116e857600080fd5b6116f182611619565b9392505050565b602080825282518282018190526000919060409081850190868401855b828110156117445781518051855286810151878601528501518585015260609093019290850190600101611715565b5091979650505050505050565b6000806040838503121561176457600080fd5b61176d83611619565b915061177b60208401611619565b90509250929050565b600181811c9082168061179857607f821691505b6020821081036117b857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156107ab576107ab6117be565b6000602082840312156117f957600080fd5b815180151581146116f157600080fd5b818103818111156107ab576107ab6117be565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b80820281158282048414176107ab576107ab6117be565b60008261187c57634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212207312ae0c9d0fe4a6400a6900fd9cd2a58c0770f9d8ca9ce748a0f2868e71d9ee64736f6c6343000814003300000000000000000000000051a16e6aec2924e8886fc323618876e3ed0e4de5000000000000000000000000d582879453337bd149ae53ec2092b0af5281d1d7000000000000000000000000abb8621b2f4fb61f083b9f2a033a40086db9030d
Deployed Bytecode
0x60806040526004361061021a5760003560e01c806354d1f13d116101235780638da7ad23116100ab578063dd62ed3e1161006f578063dd62ed3e14610632578063f04e283e14610678578063f188e7f61461068b578063f2fde38b146106bf578063fee81cf4146106d257600080fd5b80638da7ad231461058857806395d89b41146105b557806397d75776146105ca57806398807d84146105e5578063a9059cbb1461061257600080fd5b8063715018a6116100f2578063715018a6146104fe57806379cc6790146105065780637a4e4ecf146105265780638456cb59146105465780638da5cb5b1461055b57600080fd5b806354d1f13d146104885780635c975abb146104905780636198e339146104a857806370a08231146104c857600080fd5b806325692962116101a6578063358b816611610175578063358b8166146103dc5780633f4ba83a1461040957806342966c681461041e5780634a4ee7b11461043e578063514e62fc1461045157600080fd5b806325692962146103655780632de948071461036d578063313ce567146103a0578063333271d0146103bc57600080fd5b8063183a4f6e116101ed578063183a4f6e146102bb5780631c10893f146102ce5780631cd64df4146102e15780631f96da371461031857806323b872dd1461034557600080fd5b806306fdde031461021f578063095ea7b31461024a5780631338736f1461027a57806318160ddd1461029c575b600080fd5b34801561022b57600080fd5b50610234610705565b60405161024191906115cb565b60405180910390f35b34801561025657600080fd5b5061026a610265366004611635565b610797565b6040519015158152602001610241565b34801561028657600080fd5b5061029a61029536600461165f565b6107b1565b005b3480156102a857600080fd5b506002545b604051908152602001610241565b61029a6102c9366004611681565b61095b565b61029a6102dc366004611635565b610968565b3480156102ed57600080fd5b5061026a6102fc366004611635565b638b78c6d8600c90815260009290925260209091205481161490565b34801561032457600080fd5b506102ad610333366004611681565b60096020526000908152604090205481565b34801561035157600080fd5b5061026a61036036600461169a565b61097e565b61029a6109a2565b34801561037957600080fd5b506102ad6103883660046116d6565b638b78c6d8600c908152600091909152602090205490565b3480156103ac57600080fd5b5060405160128152602001610241565b3480156103c857600080fd5b5061029a6103d736600461165f565b6109f2565b3480156103e857600080fd5b506102ad6103f73660046116d6565b60086020526000908152604090205481565b34801561041557600080fd5b5061029a610a7a565b34801561042a57600080fd5b5061029a610439366004611681565b610a8d565b61029a61044c366004611635565b610a97565b34801561045d57600080fd5b5061026a61046c366004611635565b638b78c6d8600c90815260009290925260209091205416151590565b61029a610aa9565b34801561049c57600080fd5b5060055460ff1661026a565b3480156104b457600080fd5b5061029a6104c3366004611681565b610ae5565b3480156104d457600080fd5b506102ad6104e33660046116d6565b6001600160a01b031660009081526020819052604090205490565b61029a610e27565b34801561051257600080fd5b5061029a610521366004611635565b610e3b565b34801561053257600080fd5b5061029a610541366004611635565b610e50565b34801561055257600080fd5b5061029a610f3c565b34801561056757600080fd5b50638b78c6d819545b6040516001600160a01b039091168152602001610241565b34801561059457600080fd5b506105a86105a33660046116d6565b610f4f565b60405161024191906116f8565b3480156105c157600080fd5b50610234610fe2565b3480156105d657600080fd5b506105706002604360981b0181565b3480156105f157600080fd5b506102ad6106003660046116d6565b60076020526000908152604090205481565b34801561061e57600080fd5b5061026a61062d366004611635565b610ff1565b34801561063e57600080fd5b506102ad61064d366004611751565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b61029a6106863660046116d6565b610fff565b34801561069757600080fd5b506105707f000000000000000000000000d582879453337bd149ae53ec2092b0af5281d1d781565b61029a6106cd3660046116d6565b61103c565b3480156106de57600080fd5b506102ad6106ed3660046116d6565b63389a75e1600c908152600091909152602090205490565b60606003805461071490611784565b80601f016020809104026020016040519081016040528092919081815260200182805461074090611784565b801561078d5780601f106107625761010080835404028352916020019161078d565b820191906000526020600020905b81548152906001019060200180831161077057829003601f168201915b5050505050905090565b6000336107a5818585611063565b60019150505b92915050565b6107b9611075565b816000036107da5760405163162908e360e11b815260040160405180910390fd5b60008181526009602052604081205490036108085760405163f38bb1ad60e01b815260040160405180910390fd5b33600090815260076020526040812080548492906108279084906117d4565b9091555050336000818152600660209081526040808320815160608101835287815280840187815242828501908152835460018082018655948852959096209151600390950290910193845551908301559151600290910155516323b872dd60e01b81526004810191909152306024820152604481018390526001600160a01b037f000000000000000000000000d582879453337bd149ae53ec2092b0af5281d1d716906323b872dd906064016020604051808303816000875af11580156108f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091791906117e7565b506109223383611099565b60405182815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a25050565b61096533826110d4565b50565b6109706110e0565b61097a82826110fb565b5050565b60003361098c858285611107565b61099785858561117f565b506001949350505050565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b60016109fd816111de565b60648211610a1e57604051631bc4bcf760e21b815260040160405180910390fd5b60008381526009602090815260409182902080549085905582518681529182018190529181018490527f0de1269906fcaa631bbf70b295a7d636351c0e9f4fb7825498bdda2ff94ff4949060600160405180910390a150505050565b6001610a85816111de565b610965611204565b6109653382611256565b610a9f6110e0565b61097a82826110d4565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b610aed611075565b3360009081526006602052604081205490819003610b1e57604051632cdb939b60e21b815260040160405180910390fd5b6000610b2b600183611809565b905080831115610b4e57604051632d0483c560e21b815260040160405180910390fd5b336000908152600660205260408120805485908110610b6f57610b6f61181c565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905082600114610c3e57336000908152600660205260409020805483908110610bd157610bd161181c565b906000526020600020906003020160066000336001600160a01b03166001600160a01b031681526020019081526020016000208581548110610c1557610c1561181c565b600091825260209091208254600390920201908155600180830154908201556002918201549101555b336000908152600660205260409020805480610c5c57610c5c611832565b60008281526020808220600360001990940193840201828155600181018390556002019190915591558101516040820151610c9791906117d4565b421015610cb757604051636100d92960e11b815260040160405180910390fd5b80513360009081526007602052604081208054909190610cd8908490611809565b9091555050602080820180516000908152600990925260408220549051835160649291610d0491611848565b610d0e9190611848565b610d18919061185f565b33600090815260086020526040812080549293508392909190610d3c9084906117d4565b90915550508151610d4e903390611256565b815160405163a9059cbb60e01b815233600482015260248101919091527f000000000000000000000000d582879453337bd149ae53ec2092b0af5281d1d76001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015610dbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de291906117e7565b508151604080519182526020820183905233917f3f2f29fa02cc34566ac167b446be0be9e0254cac18eda93b2dfe6a7a7c8affb9910160405180910390a25050505050565b610e2f6110e0565b610e39600061128c565b565b610e46823383611107565b61097a8282611256565b6001610e5b816111de565b6001600160a01b038316610e825760405163d92e233d60e01b815260040160405180910390fd5b81600003610ea35760405163162908e360e11b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490527f000000000000000000000000d582879453337bd149ae53ec2092b0af5281d1d7169063a9059cbb906044016020604051808303816000875af1158015610f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3691906117e7565b50505050565b6001610f47816111de565b6109656112ca565b6001600160a01b0381166000908152600660209081526040808320805482518185028101850190935280835260609492939192909184015b82821015610fd75783829060005260206000209060030201604051806060016040529081600082015481526020016001820154815260200160028201548152505081526020019060010190610f87565b505050509050919050565b60606004805461071490611784565b6000336107a581858561117f565b6110076110e0565b63389a75e1600c52806000526020600c20805442111561102f57636f5e88186000526004601cfd5b600090556109658161128c565b6110446110e0565b8060601b61105a57637448fbae6000526004601cfd5b6109658161128c565b6110708383836001611307565b505050565b60055460ff1615610e395760405163d93c066560e01b815260040160405180910390fd5b6001600160a01b0382166110c85760405163ec442f0560e01b8152600060048201526024015b60405180910390fd5b61097a600083836113dc565b61097a82826000611425565b638b78c6d819543314610e39576382b429006000526004601cfd5b61097a82826001611425565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610f36578181101561117057604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064016110bf565b610f3684848484036000611307565b6001600160a01b0383166111a957604051634b637e8f60e11b8152600060048201526024016110bf565b6001600160a01b0382166111d35760405163ec442f0560e01b8152600060048201526024016110bf565b6110708383836113dc565b638b78c6d8600c5233600052806020600c205416610965576382b429006000526004601cfd5b61120c61147e565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b03821661128057604051634b637e8f60e11b8152600060048201526024016110bf565b61097a826000836113dc565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b6112d2611075565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586112393390565b6001600160a01b0384166113315760405163e602df0560e01b8152600060048201526024016110bf565b6001600160a01b03831661135b57604051634a1406b160e11b8152600060048201526024016110bf565b6001600160a01b0380851660009081526001602090815260408083209387168352929052208290558015610f3657826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516113ce91815260200190565b60405180910390a350505050565b6001600160a01b038316158015906113fc57506001600160a01b03821615155b1561141a5760405163a4420a9560e01b815260040160405180910390fd5b6110708383836114a1565b638b78c6d8600c52826000526020600c20805483811783611447575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b60055460ff16610e3957604051638dfc202b60e01b815260040160405180910390fd5b6001600160a01b0383166114cc5780600260008282546114c191906117d4565b9091555061153e9050565b6001600160a01b0383166000908152602081905260409020548181101561151f5760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016110bf565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b03821661155a57600280548290039055611579565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516115be91815260200190565b60405180910390a3505050565b600060208083528351808285015260005b818110156115f8578581018301518582016040015282016115dc565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461163057600080fd5b919050565b6000806040838503121561164857600080fd5b61165183611619565b946020939093013593505050565b6000806040838503121561167257600080fd5b50508035926020909101359150565b60006020828403121561169357600080fd5b5035919050565b6000806000606084860312156116af57600080fd5b6116b884611619565b92506116c660208501611619565b9150604084013590509250925092565b6000602082840312156116e857600080fd5b6116f182611619565b9392505050565b602080825282518282018190526000919060409081850190868401855b828110156117445781518051855286810151878601528501518585015260609093019290850190600101611715565b5091979650505050505050565b6000806040838503121561176457600080fd5b61176d83611619565b915061177b60208401611619565b90509250929050565b600181811c9082168061179857607f821691505b6020821081036117b857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156107ab576107ab6117be565b6000602082840312156117f957600080fd5b815180151581146116f157600080fd5b818103818111156107ab576107ab6117be565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b80820281158282048414176107ab576107ab6117be565b60008261187c57634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212207312ae0c9d0fe4a6400a6900fd9cd2a58c0770f9d8ca9ce748a0f2868e71d9ee64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000051a16e6aec2924e8886fc323618876e3ed0e4de5000000000000000000000000d582879453337bd149ae53ec2092b0af5281d1d7000000000000000000000000abb8621b2f4fb61f083b9f2a033a40086db9030d
-----Decoded View---------------
Arg [0] : _gameMaster (address): 0x51a16E6AEc2924e8886fc323618876e3ED0e4dE5
Arg [1] : _glory (address): 0xd582879453337BD149Ae53EC2092B0af5281d1D7
Arg [2] : _blastGovernor (address): 0xAbb8621b2F4FB61f083b9f2a033A40086DB9030d
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000051a16e6aec2924e8886fc323618876e3ed0e4de5
Arg [1] : 000000000000000000000000d582879453337bd149ae53ec2092b0af5281d1d7
Arg [2] : 000000000000000000000000abb8621b2f4fb61f083b9f2a033a40086db9030d
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.