More Info
Private Name Tags
ContractCreator
Multichain Info
No addresses found
Loading...
Loading
Minimal Proxy Contract for 0x7e28a1d82c5b7cee795affd555a398be18301f71
Contract Name:
GameLockStaking
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 "./Ownable.sol"; import {IBlast, IBlastPoints} from "./interfaces/IBlast.sol"; import {IGameLockStakingFactory} from "./interfaces/IGameLockStakingFactory.sol"; contract GameLockStaking is Ownable { bool private initialized = false; uint256 public constant MIN_LOCK_DURATION = 15 days; uint256 public constant MAX_LOCK_DURATION = 180 days; IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002); IGameLockStakingFactory public factory; event Staked(address indexed user, uint256 amount, uint256 duration); event Unstaked(address indexed user, uint256 amount); event GasClaimed(address indexed user, uint256 amount); event YieldClaimed(address indexed user, uint256 amount); event WithdrawnAll(address indexed recipient, uint256 amount); uint256 public dueTime; uint256 public stakeChangesAt; uint256 public totalStaked; uint256 public totalYield; uint256 public totalGas; uint256 public lockedValue; constructor() {} function initialize( address _initialOwner, address _blastPointsAddress, address _pointsOperator, address _factory ) public { require(!initialized, "GameLockStaking: Initialized before"); initialized = true; _owner = _initialOwner; factory = IGameLockStakingFactory(_factory); BLAST.configureClaimableGas(); IBlastPoints(_blastPointsAddress).configurePointsOperator( _pointsOperator ); BLAST.configureClaimableYield(); } function claimAllGas() external { uint256 gasReceived = BLAST.claimMaxGas(address(this), owner()); require(gasReceived > 0, "GameLockStaking: No gas"); totalGas += gasReceived; emit GasClaimed(owner(), gasReceived); } function claimAllYield() external { uint256 yieldReceived = BLAST.claimAllYield( address(this), address(this) ); require(yieldReceived > 0, "GameLockStaking: No yield"); totalYield += yieldReceived; emit YieldClaimed(owner(), yieldReceived); payable(owner()).transfer(yieldReceived); } function stake(uint256 _duration) external payable onlyOwner { require(msg.value > 0, "GameLockStaking: Zero amount"); require(_duration > 0, "GameLockStaking: Invalid duration"); require( _duration % MIN_LOCK_DURATION == 0, "GameLockStaking: Invalid duration - must be multiple of 15 days" ); require( _duration <= MAX_LOCK_DURATION, "GameLockStaking: Max lock - 180 days" ); require( _duration >= dueTime - stakeChangesAt, "GameLockStaking: Less than last duration" ); uint256 decreaseAmount = 0; if (dueTime > block.timestamp) { decreaseAmount = totalStaked * (dueTime - block.timestamp); } totalStaked += msg.value; dueTime = block.timestamp + _duration; lockedValue += (totalStaked * _duration) - decreaseAmount; stakeChangesAt = block.timestamp; emit Staked(owner(), msg.value, _duration); } function unstake(uint256 _amount) external onlyOwner { require(totalStaked > 0, "GameLockStaking: Not staked"); require( _amount > 0 && _amount <= totalStaked, "GameLockStaking: Invalid amount" ); require(block.timestamp >= dueTime, "GameLockStaking: Not due yet"); totalStaked -= _amount; emit Unstaked(owner(), _amount); payable(owner()).transfer(_amount); } function withdrawAll() external onlyOwner { uint256 balance = address(this).balance; require(balance > 0, "GameLockStaking: Empty balance"); require(block.timestamp >= dueTime, "GameLockStaking: Not due yet"); totalStaked = 0; emit WithdrawnAll(owner(), balance); payable(owner()).transfer(balance); } function transferOwnership(address _newOwner) public override onlyOwner { require(_newOwner != address(0), "Ownable: Zero Address"); address _currentOwner = _owner; _owner = _newOwner; emit OwnershipTransferred(_currentOwner, _newOwner); factory.setCloneNewOwner(_newOwner, _currentOwner); } function readClaimableYield() external view returns (uint256) { return BLAST.readClaimableYield(address(this)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; contract Ownable { address public _owner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); constructor() {} modifier onlyOwner() { require(isOwner(), "Ownable: Not owner"); _; } function owner() public view returns (address) { return _owner; } function isOwner() public view returns (bool) { return msg.sender == _owner; } function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } function transferOwnership(address newOwner) public virtual onlyOwner { require( newOwner != address(0), "Ownable: Zero Address" ); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; enum YieldMode { AUTOMATIC, VOID, CLAIMABLE } enum GasMode { VOID, CLAIMABLE } interface IBlast { // 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 ); } interface IERC20Rebasing is IERC20 { // changes the yield mode of the caller and update the balance // to reflect the configuration function configure(YieldMode) external returns (uint256); // "claimable" yield mode accounts can call this this claim their yield // to another address function claim( address recipient, uint256 amount ) external returns (uint256); // read the claimable amount for an account function getClaimableAmount( address account ) external view returns (uint256); } interface IBlastPoints { function configurePointsOperator(address operator) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; interface IGameLockStakingFactory { function createGameLockStakingClone() external returns (address); function setGameLockStakingImplementation( address _gameLockStakingImplementation ) external; function setPointsOperator(address _pointsOperator) external; function setCloneNewOwner( address _newOwner, address _currentOwner ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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); }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-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 ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"GasClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawnAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"YieldClaimed","type":"event"},{"inputs":[],"name":"BLAST","outputs":[{"internalType":"contract IBlast","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_LOCK_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_LOCK_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimAllGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimAllYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dueTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IGameLockStakingFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_initialOwner","type":"address"},{"internalType":"address","name":"_blastPointsAddress","type":"address"},{"internalType":"address","name":"_pointsOperator","type":"address"},{"internalType":"address","name":"_factory","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockedValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readClaimableYield","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"stakeChangesAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalYield","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.