More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 219 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Stake | 20516872 | 7 hrs ago | IN | 0 ETH | 0.00023967 | ||||
Stake | 20507281 | 39 hrs ago | IN | 0 ETH | 0.0003228 | ||||
Claim | 20507250 | 39 hrs ago | IN | 0 ETH | 0.00020096 | ||||
Claim | 20507141 | 39 hrs ago | IN | 0 ETH | 0.00010685 | ||||
Withdraw | 20507083 | 39 hrs ago | IN | 0 ETH | 0.00017153 | ||||
Claim | 20507070 | 39 hrs ago | IN | 0 ETH | 0.00011743 | ||||
Stake | 20495608 | 3 days ago | IN | 0 ETH | 0.00013828 | ||||
Claim | 20495598 | 3 days ago | IN | 0 ETH | 0.00008719 | ||||
Withdraw | 20495595 | 3 days ago | IN | 0 ETH | 0.00010439 | ||||
Stake | 20492493 | 3 days ago | IN | 0 ETH | 0.0004241 | ||||
Stake | 20489989 | 4 days ago | IN | 0 ETH | 0.00096309 | ||||
Withdraw | 20489953 | 4 days ago | IN | 0 ETH | 0.00100656 | ||||
Claim | 20489947 | 4 days ago | IN | 0 ETH | 0.00057784 | ||||
Withdraw | 20460036 | 8 days ago | IN | 0 ETH | 0.00269308 | ||||
Claim | 20460024 | 8 days ago | IN | 0 ETH | 0.00166262 | ||||
Withdraw | 20434749 | 11 days ago | IN | 0 ETH | 0.00247341 | ||||
Claim | 20434745 | 11 days ago | IN | 0 ETH | 0.00196113 | ||||
Claim | 20421413 | 13 days ago | IN | 0 ETH | 0.00087154 | ||||
Withdraw | 20421410 | 13 days ago | IN | 0 ETH | 0.00136128 | ||||
Claim | 20418326 | 14 days ago | IN | 0 ETH | 0.00038774 | ||||
Claim | 20398024 | 16 days ago | IN | 0 ETH | 0.00015158 | ||||
Stake | 20397582 | 16 days ago | IN | 0 ETH | 0.00022179 | ||||
Withdraw | 20397567 | 16 days ago | IN | 0 ETH | 0.00021534 | ||||
Claim | 20397555 | 16 days ago | IN | 0 ETH | 0.00014298 | ||||
Stake | 20384612 | 18 days ago | IN | 0 ETH | 0.00065373 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
LendsStake
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.21; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract LendsStake is Ownable, ReentrancyGuard { using SafeERC20 for IERC20; event Stake(address indexed wallet, uint256 amount, uint256 date); event Withdraw(address indexed wallet, uint256 amount, uint256 date); event Claimed( address indexed wallet, address indexed rewardToken, uint256 amount ); event RewardTokenChanged( address indexed oldRewardToken, uint256 returnedAmount, address indexed newRewardToken ); event GovernanceTokenChanged( address indexed oldGovernanceToken, address indexed newGovernanceToken ); event LockTimePeriodChanged(uint48 lockTimePeriod); event StakeRewardFactorChanged(uint256 stakeRewardFactor); event StakeRewardEndTimeChanged(uint48 stakeRewardEndTime); event RewardsBurned(address indexed staker, uint256 amount); event ERC20TokensRemoved( address indexed tokenAddress, address indexed receiver, uint256 amount ); uint48 public constant MAX_TIME = type(uint48).max; // = 2^48 - 1 struct User { uint48 stakeTime; uint48 unlockTime; uint160 stakeAmount; uint256 accumulatedRewards; } mapping(address => User) public userMap; uint256 public tokenTotalStaked; // sum of all staked tokens address public immutable stakingToken; // address of token which can be staked into this contract address public governanceToken; // address of governance token address public rewardToken; // address of reward token /** * Using block.timestamp instead of block.number for reward calculation * 1) Easier to handle for users * 2) Should result in same rewards across different chain with different block times * 3) "The current block timestamp must be strictly larger than the timestamp of the last block, ... * but the only guarantee is that it will be somewhere between the timestamps ... * of two consecutive blocks in the canonical chain." * https://docs.soliditylang.org/en/v0.7.6/cheatsheet.html?highlight=block.timestamp#global-variables */ uint48 public lockTimePeriod; // time in seconds a user has to wait after calling unlock until staked token can be withdrawn uint48 public stakeRewardEndTime; // unix time in seconds when the reward scheme will end uint256 public stakeRewardFactor; // time in seconds * amount of staked token to receive 1 reward token constructor( address _stakingToken, address _governanceToken, address _rewardToken, uint48 _lockTimePeriod ) Ownable(msg.sender) { require(_stakingToken != address(0), "stakingToken.address == 0"); require(_governanceToken != address(0), "governanceToken.address == 0"); require(_rewardToken != address(0), "rewardToken.address == 0"); require(_lockTimePeriod < 366 days, "lockTimePeriod >= 366 days"); stakingToken = _stakingToken; governanceToken = _governanceToken; rewardToken = _rewardToken; lockTimePeriod = _lockTimePeriod; // set some defaults stakeRewardFactor = 2439 * 1 days; // default : a user has to stake 2439 token for 1 day to receive 1 reward token i.e. 15% APY stakeRewardEndTime = uint48(block.timestamp + 366 days); // default : reward scheme ends in 1 year } /** * based on OpenZeppelin SafeCast v4.3 * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.3/contracts/utils/math/SafeCast.sol */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "value doesn't fit in 48 bits"); return uint48(value); } function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "value doesn't fit in 160 bits"); return uint160(value); } /** * External API functions */ function stakeTime( address _staker ) external view returns (uint48 dateTime) { return userMap[_staker].stakeTime; } function stakeAmount( address _staker ) external view returns (uint256 balance) { return userMap[_staker].stakeAmount; } // redundant with stakeAmount() for compatibility function balanceOf( address _staker ) external view returns (uint256 balance) { return userMap[_staker].stakeAmount; } function userAccumulatedRewards( address _staker ) external view returns (uint256 rewards) { return userMap[_staker].accumulatedRewards; } /** * @dev return unix epoch time when staked tokens will be unlocked * @dev return MAX_INT_UINT48 = 2**48-1 if user has no token staked * @dev this always allows an easy check with : require(block.timestamp > getUnlockTime(account)); * @return unlockTime unix epoch time in seconds */ function getUnlockTime( address _staker ) public view returns (uint48 unlockTime) { return userMap[_staker].stakeAmount > 0 ? userMap[_staker].unlockTime : MAX_TIME; } /** * @return balance of reward tokens held by this contract */ function getRewardTokenBalance() public view returns (uint256 balance) { if (rewardToken == address(0)) return 0; balance = IERC20(rewardToken).balanceOf(address(this)); if (stakingToken == rewardToken) { balance -= tokenTotalStaked; } } // onlyOwner -------------------------------------------------- /** * @notice setting rewardToken to address(0) disables claim/mint * @notice if there was a reward token set before, return remaining tokens to msg.sender/admin * @param newRewardToken address */ function setRewardToken( address newRewardToken ) external nonReentrant onlyOwner { address oldRewardToken = rewardToken; uint256 rewardBalance = getRewardTokenBalance(); // balance of oldRewardToken if (rewardBalance > 0) { IERC20(oldRewardToken).safeTransfer(msg.sender, rewardBalance); } rewardToken = newRewardToken; emit RewardTokenChanged(oldRewardToken, rewardBalance, newRewardToken); } /** * @notice setting governanceToken to address(0) disables staking/unstaking * @param newGovernanceToken address */ function setGovernanceToken( address newGovernanceToken ) external nonReentrant onlyOwner { address oldGovernanceToken = governanceToken; governanceToken = newGovernanceToken; emit GovernanceTokenChanged(oldGovernanceToken, governanceToken); } /** * @notice set time a user has to wait after calling unlock until staked token can be withdrawn * @param _lockTimePeriod time in seconds */ function setLockTimePeriod(uint48 _lockTimePeriod) external onlyOwner { lockTimePeriod = _lockTimePeriod; emit LockTimePeriodChanged(_lockTimePeriod); } /** * @notice see calculateUserClaimableReward() docs * @dev requires that reward token has the same decimals as stake token * @param _stakeRewardFactor time in seconds * amount of staked token to receive 1 reward token */ function setStakeRewardFactor( uint256 _stakeRewardFactor ) external onlyOwner { stakeRewardFactor = _stakeRewardFactor; emit StakeRewardFactorChanged(_stakeRewardFactor); } /** * @notice set block time when stake reward scheme will end * @param _stakeRewardEndTime unix time in seconds */ function setStakeRewardEndTime( uint48 _stakeRewardEndTime ) external onlyOwner { require( stakeRewardEndTime > block.timestamp, "time has to be in the future" ); stakeRewardEndTime = _stakeRewardEndTime; emit StakeRewardEndTimeChanged(_stakeRewardEndTime); } /** * ADMIN_ROLE has to set BURNER_ROLE * allows an external (lottery token sale) contract to substract rewards */ function burnRewards(address _staker, uint256 _amount) external onlyOwner { User storage user = _updateRewards(_staker); if (_amount < user.accumulatedRewards) { user.accumulatedRewards -= _amount; // safe } else { user.accumulatedRewards = 0; // burn at least all what's there } emit RewardsBurned(_staker, _amount); } /** msg.sender external view convenience functions *********************************/ function stakeAmount_msgSender() public view returns (uint256) { return userMap[msg.sender].stakeAmount; } function stakeTime_msgSender() external view returns (uint48) { return userMap[msg.sender].stakeTime; } function getUnlockTime_msgSender() external view returns (uint48 unlockTime) { return getUnlockTime(msg.sender); } function userClaimableRewards_msgSender() external view returns (uint256) { return userClaimableRewards(msg.sender); } function userAccumulatedRewards_msgSender() external view returns (uint256) { return userMap[msg.sender].accumulatedRewards; } function userTotalRewards_msgSender() external view returns (uint256) { return userTotalRewards(msg.sender); } function getEarnedRewardTokens_msgSender() external view returns (uint256) { return getEarnedRewardTokens(msg.sender); } /** public external view functions (also used internally) **************************/ /** * calculates unclaimed rewards * unclaimed rewards = expired time since last stake/unstake transaction * current staked amount * * We have to cover 6 cases here : * 1) block time < stake time < end time : should never happen => error * 2) block time < end time < stake time : should never happen => error * 3) end time < block time < stake time : should never happen => error * 4) end time < stake time < block time : staked after reward period is over => no rewards * 5) stake time < block time < end time : end time in the future * 6) stake time < end time < block time : end time in the past & staked before * @param _staker address * @return claimableRewards = timePeriod * stakeAmount */ function userClaimableRewards( address _staker ) public view returns (uint256) { User storage user = userMap[_staker]; // case 1) 2) 3) // stake time in the future - should never happen - actually an (internal ?) error if (block.timestamp <= user.stakeTime) return 0; // case 4) // staked after reward period is over => no rewards // end time < stake time < block time if (stakeRewardEndTime <= user.stakeTime) return 0; uint256 timePeriod; // case 5 // we have not reached the end of the reward period // stake time < block time < end time if (block.timestamp <= stakeRewardEndTime) { timePeriod = block.timestamp - user.stakeTime; // covered by case 1) 2) 3) 'if' } else { // case 6 // user staked before end of reward period , but that is in the past now // stake time < end time < block time timePeriod = stakeRewardEndTime - user.stakeTime; // covered case 4) } return timePeriod * user.stakeAmount; } function userTotalRewards(address _staker) public view returns (uint256) { return userClaimableRewards(_staker) + userMap[_staker].accumulatedRewards; } function getEarnedRewardTokens( address _staker ) public view returns (uint256 claimableRewardTokens) { if (address(rewardToken) == address(0) || stakeRewardFactor == 0) { return 0; } else { return userTotalRewards(_staker) / stakeRewardFactor; // safe } } /** * @dev whenver the staked balance changes do ... * * @dev calculate userClaimableRewards = previous staked amount * (current time - last stake time) * @dev add userClaimableRewards to userAccumulatedRewards * @dev reset userClaimableRewards to 0 by setting stakeTime to current time * @dev not used as doing it inline, local, within a function consumes less gas * * @return user reference pointer for further processing */ function _updateRewards( address _staker ) internal returns (User storage user) { // calculate reward credits using previous staking amount and previous time period // add new reward credits to already accumulated reward credits user = userMap[_staker]; user.accumulatedRewards += userClaimableRewards(_staker); // update stake Time to current time (start new reward period) // will also reset userClaimableRewards() user.stakeTime = toUint48(block.timestamp); } /** * add stake token to staking pool * @dev requires the token to be approved for transfer * @dev we assume that (our) stake token is not malicious, so no special checks * @param _amount of token to be staked */ function _stake(uint256 _amount) internal returns (uint256) { require(_amount > 0, "stake amount must be > 0"); require( IERC20(governanceToken).balanceOf(address(this)) >= _amount, "staking limit has been reached" ); User storage user = _updateRewards(msg.sender); // update rewards and return reference to user user.stakeAmount = toUint160(user.stakeAmount + _amount); tokenTotalStaked += _amount; user.unlockTime = toUint48(block.timestamp + lockTimePeriod); // using SafeERC20 for IERC20 => will revert in case of error IERC20(stakingToken).safeTransferFrom( msg.sender, address(this), _amount ); IERC20(governanceToken).safeTransfer(msg.sender, _amount); emit Stake(msg.sender, _amount, toUint48(block.timestamp)); // = user.stakeTime return _amount; } /** * withdraw staked token, ... * do not withdraw rewards token (it might not be worth the gas) * @return amount of tokens sent to user's account */ function _withdraw(uint256 amount) internal returns (uint256) { require(amount > 0, "amount to withdraw not > 0"); require( block.timestamp > getUnlockTime(msg.sender), "staked tokens are still locked" ); require( IERC20(governanceToken).balanceOf(msg.sender) >= amount, "not enough staked tokens" ); User storage user = _updateRewards(msg.sender); // update rewards and return reference to user require(amount <= user.stakeAmount, "withdraw amount > staked amount"); user.stakeAmount -= toUint160(amount); tokenTotalStaked -= amount; // using SafeERC20 for IERC20 => will revert in case of error IERC20(stakingToken).safeTransfer(msg.sender, amount); IERC20(governanceToken).safeTransferFrom( msg.sender, address(this), amount ); emit Withdraw(msg.sender, amount, toUint48(block.timestamp)); // = user.stakeTime return amount; } /** * claim reward tokens for accumulated reward credits * ... but do not unstake staked token */ function _claim() internal returns (uint256) { require(rewardToken != address(0), "no reward token contract"); uint256 earnedRewardTokens = getEarnedRewardTokens(msg.sender); require(earnedRewardTokens > 0, "no tokens to claim"); // like _updateRewards() , but reset all rewards to 0 User storage user = userMap[msg.sender]; user.accumulatedRewards = 0; user.stakeTime = toUint48(block.timestamp); // will reset userClaimableRewards to 0 // user.stakeAmount = unchanged require( earnedRewardTokens <= getRewardTokenBalance(), "not enough reward tokens" ); // redundant but dedicated error message IERC20(rewardToken).safeTransfer(msg.sender, earnedRewardTokens); emit Claimed(msg.sender, rewardToken, earnedRewardTokens); return earnedRewardTokens; } function stake(uint256 _amount) external nonReentrant returns (uint256) { return _stake(_amount); } function claim() external nonReentrant returns (uint256) { return _claim(); } function withdraw(uint256 amount) external nonReentrant returns (uint256) { return _withdraw(amount); } function withdrawAll() external nonReentrant returns (uint256) { return _withdraw(stakeAmount_msgSender()); } /** * Do not accept accidently sent ETH : * If neither a receive Ether nor a payable fallback function is present, * the contract cannot receive Ether through regular transactions and throws an exception. * https://docs.soliditylang.org/en/v0.8.7/contracts.html#receive-ether-function */ /** * @notice withdraw accidently sent ERC20 tokens * @param _tokenAddress address of token to withdraw */ function removeOtherERC20Tokens(address _tokenAddress) external onlyOwner { uint256 balance = IERC20(_tokenAddress).balanceOf(address(this)); IERC20(_tokenAddress).safeTransfer(msg.sender, balance); emit ERC20TokensRemoved(_tokenAddress, msg.sender, balance); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// 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/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_governanceToken","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint48","name":"_lockTimePeriod","type":"uint48"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20TokensRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldGovernanceToken","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernanceToken","type":"address"}],"name":"GovernanceTokenChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint48","name":"lockTimePeriod","type":"uint48"}],"name":"LockTimePeriodChanged","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":"oldRewardToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"returnedAmount","type":"uint256"},{"indexed":true,"internalType":"address","name":"newRewardToken","type":"address"}],"name":"RewardTokenChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"date","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint48","name":"stakeRewardEndTime","type":"uint48"}],"name":"StakeRewardEndTimeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"stakeRewardFactor","type":"uint256"}],"name":"StakeRewardFactorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"date","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"MAX_TIME","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"getEarnedRewardTokens","outputs":[{"internalType":"uint256","name":"claimableRewardTokens","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEarnedRewardTokens_msgSender","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardTokenBalance","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"getUnlockTime","outputs":[{"internalType":"uint48","name":"unlockTime","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUnlockTime_msgSender","outputs":[{"internalType":"uint48","name":"unlockTime","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockTimePeriod","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"removeOtherERC20Tokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newGovernanceToken","type":"address"}],"name":"setGovernanceToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"_lockTimePeriod","type":"uint48"}],"name":"setLockTimePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRewardToken","type":"address"}],"name":"setRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"_stakeRewardEndTime","type":"uint48"}],"name":"setStakeRewardEndTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakeRewardFactor","type":"uint256"}],"name":"setStakeRewardFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"stakeAmount","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakeAmount_msgSender","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakeRewardEndTime","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakeRewardFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"stakeTime","outputs":[{"internalType":"uint48","name":"dateTime","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakeTime_msgSender","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenTotalStaked","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":"address","name":"_staker","type":"address"}],"name":"userAccumulatedRewards","outputs":[{"internalType":"uint256","name":"rewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"userAccumulatedRewards_msgSender","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"userClaimableRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"userClaimableRewards_msgSender","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMap","outputs":[{"internalType":"uint48","name":"stakeTime","type":"uint48"},{"internalType":"uint48","name":"unlockTime","type":"uint48"},{"internalType":"uint160","name":"stakeAmount","type":"uint160"},{"internalType":"uint256","name":"accumulatedRewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"userTotalRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"userTotalRewards_msgSender","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162001d9b38038062001d9b8339810160408190526200003491620002cf565b33806200005c57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620000678162000262565b50600180556001600160a01b038416620000c45760405162461bcd60e51b815260206004820152601960248201527f7374616b696e67546f6b656e2e61646472657373203d3d203000000000000000604482015260640162000053565b6001600160a01b0383166200011c5760405162461bcd60e51b815260206004820152601c60248201527f676f7665726e616e6365546f6b656e2e61646472657373203d3d203000000000604482015260640162000053565b6001600160a01b038216620001745760405162461bcd60e51b815260206004820152601860248201527f726577617264546f6b656e2e61646472657373203d3d20300000000000000000604482015260640162000053565b6301e285008165ffffffffffff1610620001d15760405162461bcd60e51b815260206004820152601a60248201527f6c6f636b54696d65506572696f64203e3d203336362064617973000000000000604482015260640162000053565b6001600160a01b03848116608052600480546001600160a01b031916858316179055600580549184166001600160d01b031990921691909117600160a01b65ffffffffffff841602179055630c8f7a8060065562000234426301e2850062000338565b6005601a6101000a81548165ffffffffffff021916908365ffffffffffff1602179055505050505062000360565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b0381168114620002ca57600080fd5b919050565b60008060008060808587031215620002e657600080fd5b620002f185620002b2565b93506200030160208601620002b2565b92506200031160408601620002b2565b9150606085015165ffffffffffff811681146200032d57600080fd5b939692955090935050565b808201808211156200035a57634e487b7160e01b600052601160045260246000fd5b92915050565b608051611a0a620003916000396000818161042e015281816109ca01528181610fca01526114b80152611a0a6000f3fe608060405234801561001057600080fd5b506004361061023d5760003560e01c80638da5cb5b1161013b578063de3717fc116100b8578063f3b95cd71161007c578063f3b95cd714610592578063f6a3f3cf146105a5578063f7c618c1146105b8578063f8570170146105cb578063f96dae0a146105de57600080fd5b8063de3717fc1461053e578063dfdf35c414610546578063ee2d505e14610559578063ee61e0cd1461056c578063f2fde38b1461057f57600080fd5b8063a694fc3a116100ff578063a694fc3a146104e2578063aaa748d3146104f5578063bf135267146103ee578063d953a86714610512578063dbed1e881461052b57600080fd5b80638da5cb5b146104955780638efb31c7146104a657806393ce5343146104b95780639a7cc1b8146104c1578063a38a57c4146104c957600080fd5b80635951eff1116101c957806372f702f31161018d57806372f702f314610429578063853828b614610468578063872b26da1461047057806387f075d9146104795780638aee81271461048257600080fd5b80635951eff1146103ab5780635bd4b5df146103c05780636bb64e23146103c857806370a08231146103ee578063715018a61461042157600080fd5b8063269499841161021057806326949984146102f45780632bcc23f8146103015780632e1a7d4d146103885780633cb2efc91461039b5780634e71d92d146103a357600080fd5b80630584bd091461024257806307dc1e1a1461026857806309ef67e6146102805780632170e472146102ac575b600080fd5b610255610250366004611829565b6105f1565b6040519081526020015b60405180910390f35b33600090815260026020526040902060010154610255565b61025561028e366004611829565b6001600160a01b031660009081526002602052604090206001015490565b6102dd6102ba366004611829565b6001600160a01b031660009081526002602052604090205465ffffffffffff1690565b60405165ffffffffffff909116815260200161025f565b6102dd65ffffffffffff81565b61035061030f366004611829565b6002602052600090815260409020805460019091015465ffffffffffff80831692600160301b810490911691600160601b9091046001600160a01b03169084565b6040805165ffffffffffff95861681529490931660208501526001600160a01b0390911691830191909152606082015260800161025f565b610255610396366004611844565b6106d0565b6102dd6106f3565b610255610703565b6103be6103b9366004611829565b610723565b005b6102556107f0565b61025533600090815260026020526040902054600160601b90046001600160a01b031690565b6102556103fc366004611829565b6001600160a01b03908116600090815260026020526040902054600160601b90041690565b6103be6107fb565b6104507f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161025f565b61025561080f565b61025560035481565b61025560065481565b6103be610490366004611829565b610847565b6000546001600160a01b0316610450565b6103be6104b4366004611844565b6108ee565b610255610932565b6102556109fe565b6005546102dd90600160d01b900465ffffffffffff1681565b6102556104f0366004611844565b610a09565b3360009081526002602052604090205465ffffffffffff166102dd565b6005546102dd90600160a01b900465ffffffffffff1681565b6102dd610539366004611829565b610a1c565b610255610a80565b6103be61055436600461185d565b610a8b565b610255610567366004611829565b610b4e565b6103be61057a36600461185d565b610b8c565b6103be61058d366004611829565b610bec565b6103be6105a0366004611885565b610c27565b6102556105b3366004611829565b610cb7565b600554610450906001600160a01b031681565b6103be6105d9366004611829565b610ce6565b600454610450906001600160a01b031681565b6001600160a01b0381166000908152600260205260408120805465ffffffffffff1642116106225750600092915050565b805460055465ffffffffffff918216600160d01b9091049091161161064a5750600092915050565b600554600090600160d01b900465ffffffffffff1642116106805781546106799065ffffffffffff16426118c5565b90506106ac565b81546005546106a19165ffffffffffff90811691600160d01b9004166118d8565b65ffffffffffff1690505b81546106c890600160601b90046001600160a01b0316826118fe565b949350505050565b60006106da610d4e565b6106e382610d78565b90506106ee60018055565b919050565b60006106fe33610a1c565b905090565b600061070d610d4e565b61071561105b565b905061072060018055565b90565b61072b6111f9565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610772573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107969190611915565b90506107ac6001600160a01b0383163383611226565b60405181815233906001600160a01b038416907f4c9443772ec3472e2ea8a88e5c31e6bb75e94541dc672d5ca2a1197ada10b5989060200160405180910390a35050565b60006106fe336105f1565b6108036111f9565b61080d600061128a565b565b6000610819610d4e565b61071561084233600090815260026020526040902054600160601b90046001600160a01b031690565b610d78565b61084f610d4e565b6108576111f9565b6005546001600160a01b0316600061086d610932565b90508015610889576108896001600160a01b0383163383611226565b600580546001600160a01b0319166001600160a01b0385811691821790925560405183815290918416907fc133375757269458a329c73a344c8ef483535870f46ed4cd332f857a5ef525d09060200160405180910390a350506108eb60018055565b50565b6108f66111f9565b60068190556040518181527f929e0b2903ee7e8bb87bf220a340db1f5551e7042e5f2567ed08117c0709fa21906020015b60405180910390a150565b6005546000906001600160a01b031661094b5750600090565b6005546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b79190611915565b6005549091506001600160a01b039081167f000000000000000000000000000000000000000000000000000000000000000090911603610720576003546106fe90826118c5565b60006106fe33610b4e565b6000610a13610d4e565b6106e3826112da565b6001600160a01b038082166000908152600260205260408120549091600160601b90910416610a515765ffffffffffff610a7a565b6001600160a01b038216600090815260026020526040902054600160301b900465ffffffffffff165b92915050565b60006106fe33610cb7565b610a936111f9565b60055442600160d01b90910465ffffffffffff1611610af95760405162461bcd60e51b815260206004820152601c60248201527f74696d652068617320746f20626520696e20746865206675747572650000000060448201526064015b60405180910390fd5b600580546001600160d01b0316600160d01b65ffffffffffff8416908102919091179091556040519081527fb8ec1a7db76539d0a932b67153298ec5ba41b1f965bd5f66e9419431d517291a90602001610927565b6005546000906001600160a01b03161580610b695750600654155b15610b7657506000919050565b600654610b8283610cb7565b610a7a919061192e565b610b946111f9565b6005805465ffffffffffff60a01b1916600160a01b65ffffffffffff8416908102919091179091556040519081527fe9f020bdf01408388704d87e8162e06252d160de9f8cc075b32ce7ebbebc263e90602001610927565b610bf46111f9565b6001600160a01b038116610c1e57604051631e4fbdf760e01b815260006004820152602401610af0565b6108eb8161128a565b610c2f6111f9565b6000610c3a83611523565b90508060010154821015610c675781816001016000828254610c5c91906118c5565b90915550610c6f9050565b600060018201555b826001600160a01b03167f33e88885e6abd26d1f3ea3b4b37c2f6e0ff31fa24c7721763eca867537bdf5d283604051610caa91815260200190565b60405180910390a2505050565b6001600160a01b038116600090815260026020526040812060010154610cdc836105f1565b610a7a9190611950565b610cee610d4e565b610cf66111f9565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f58ff585b99ade29efbc655970d10cfc8401e6ad7bf243459026c13271f88f79d90600090a3506108eb60018055565b600260015403610d7157604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b6000808211610dc95760405162461bcd60e51b815260206004820152601a60248201527f616d6f756e7420746f207769746864726177206e6f74203e20300000000000006044820152606401610af0565b610dd233610a1c565b65ffffffffffff164211610e285760405162461bcd60e51b815260206004820152601e60248201527f7374616b656420746f6b656e7320617265207374696c6c206c6f636b656400006044820152606401610af0565b600480546040516370a0823160e01b8152339281019290925283916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610e75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e999190611915565b1015610ee75760405162461bcd60e51b815260206004820152601860248201527f6e6f7420656e6f756768207374616b656420746f6b656e7300000000000000006044820152606401610af0565b6000610ef233611523565b8054909150600160601b90046001600160a01b0316831115610f565760405162461bcd60e51b815260206004820152601f60248201527f776974686472617720616d6f756e74203e207374616b656420616d6f756e74006044820152606401610af0565b610f5f83611584565b81548290600c90610f81908490600160601b90046001600160a01b0316611963565b92506101000a8154816001600160a01b0302191690836001600160a01b031602179055508260036000828254610fb791906118c5565b90915550610ff190506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385611226565b600454611009906001600160a01b03163330866115e1565b337ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5688461103542611620565b6040805192835265ffffffffffff90911660208301520160405180910390a25090919050565b6005546000906001600160a01b03166110b65760405162461bcd60e51b815260206004820152601860248201527f6e6f2072657761726420746f6b656e20636f6e747261637400000000000000006044820152606401610af0565b60006110c133610b4e565b9050600081116111085760405162461bcd60e51b81526020600482015260126024820152716e6f20746f6b656e7320746f20636c61696d60701b6044820152606401610af0565b336000908152600260205260408120600181019190915561112842611620565b815465ffffffffffff191665ffffffffffff91909116178155611149610932565b8211156111985760405162461bcd60e51b815260206004820152601860248201527f6e6f7420656e6f7567682072657761726420746f6b656e7300000000000000006044820152606401610af0565b6005546111af906001600160a01b03163384611226565b6005546040518381526001600160a01b039091169033907ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd39926839060200160405180910390a350919050565b6000546001600160a01b0316331461080d5760405163118cdaa760e01b8152336004820152602401610af0565b6040516001600160a01b0383811660248301526044820183905261128591859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611678565b505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080821161132b5760405162461bcd60e51b815260206004820152601860248201527f7374616b6520616d6f756e74206d757374206265203e203000000000000000006044820152606401610af0565b600480546040516370a0823160e01b8152309281019290925283916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139c9190611915565b10156113ea5760405162461bcd60e51b815260206004820152601e60248201527f7374616b696e67206c696d697420686173206265656e207265616368656400006044820152606401610af0565b60006113f533611523565b805490915061141e90611419908590600160601b90046001600160a01b0316611950565b611584565b81546001600160a01b0391909116600160601b026bffffffffffffffffffffffff9091161781556003805484919060009061145a908490611950565b90915550506005546114849061147f90600160a01b900465ffffffffffff1642611950565b611620565b815465ffffffffffff91909116600160301b026bffffffffffff000000000000199091161781556114e06001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330866115e1565b6004546114f7906001600160a01b03163385611226565b337f5af417134f72a9d41143ace85b0a26dce6f550f894f2cbc1eeee8810603d91b68461103542611620565b6001600160a01b0381166000908152600260205260409020611544826105f1565b8160010160008282546115579190611950565b90915550611566905042611620565b815465ffffffffffff191665ffffffffffff91909116178155919050565b60006001600160a01b038211156115dd5760405162461bcd60e51b815260206004820152601d60248201527f76616c756520646f65736e27742066697420696e2031363020626974730000006044820152606401610af0565b5090565b6040516001600160a01b03848116602483015283811660448301526064820183905261161a9186918216906323b872dd90608401611253565b50505050565b600065ffffffffffff8211156115dd5760405162461bcd60e51b815260206004820152601c60248201527f76616c756520646f65736e27742066697420696e2034382062697473000000006044820152606401610af0565b600061168d6001600160a01b038416836116db565b905080516000141580156116b25750808060200190518101906116b09190611983565b155b1561128557604051635274afe760e01b81526001600160a01b0384166004820152602401610af0565b60606116e9838360006116f0565b9392505050565b6060814710156117155760405163cd78605960e01b8152306004820152602401610af0565b600080856001600160a01b0316848660405161173191906119a5565b60006040518083038185875af1925050503d806000811461176e576040519150601f19603f3d011682016040523d82523d6000602084013e611773565b606091505b509150915061178386838361178d565b9695505050505050565b6060826117a25761179d826117e9565b6116e9565b81511580156117b957506001600160a01b0384163b155b156117e257604051639996b31560e01b81526001600160a01b0385166004820152602401610af0565b50806116e9565b8051156117f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146106ee57600080fd5b60006020828403121561183b57600080fd5b6116e982611812565b60006020828403121561185657600080fd5b5035919050565b60006020828403121561186f57600080fd5b813565ffffffffffff811681146116e957600080fd5b6000806040838503121561189857600080fd5b6118a183611812565b946020939093013593505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610a7a57610a7a6118af565b65ffffffffffff8281168282160390808211156118f7576118f76118af565b5092915050565b8082028115828204841417610a7a57610a7a6118af565b60006020828403121561192757600080fd5b5051919050565b60008261194b57634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115610a7a57610a7a6118af565b6001600160a01b038281168282160390808211156118f7576118f76118af565b60006020828403121561199557600080fd5b815180151581146116e957600080fd5b6000825160005b818110156119c657602081860181015185830152016119ac565b50600092019182525091905056fea2646970667358221220a372cdf83ea862a7432ef748f49dc47df71de72f42e59ac0cb214300579760f464736f6c634300081500330000000000000000000000002c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a000000000000000000000000da16444b8bd79618b7c7f73d898b025dc5a7f0950000000000000000000000002c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a000000000000000000000000000000000000000000000000000000000076a700
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061023d5760003560e01c80638da5cb5b1161013b578063de3717fc116100b8578063f3b95cd71161007c578063f3b95cd714610592578063f6a3f3cf146105a5578063f7c618c1146105b8578063f8570170146105cb578063f96dae0a146105de57600080fd5b8063de3717fc1461053e578063dfdf35c414610546578063ee2d505e14610559578063ee61e0cd1461056c578063f2fde38b1461057f57600080fd5b8063a694fc3a116100ff578063a694fc3a146104e2578063aaa748d3146104f5578063bf135267146103ee578063d953a86714610512578063dbed1e881461052b57600080fd5b80638da5cb5b146104955780638efb31c7146104a657806393ce5343146104b95780639a7cc1b8146104c1578063a38a57c4146104c957600080fd5b80635951eff1116101c957806372f702f31161018d57806372f702f314610429578063853828b614610468578063872b26da1461047057806387f075d9146104795780638aee81271461048257600080fd5b80635951eff1146103ab5780635bd4b5df146103c05780636bb64e23146103c857806370a08231146103ee578063715018a61461042157600080fd5b8063269499841161021057806326949984146102f45780632bcc23f8146103015780632e1a7d4d146103885780633cb2efc91461039b5780634e71d92d146103a357600080fd5b80630584bd091461024257806307dc1e1a1461026857806309ef67e6146102805780632170e472146102ac575b600080fd5b610255610250366004611829565b6105f1565b6040519081526020015b60405180910390f35b33600090815260026020526040902060010154610255565b61025561028e366004611829565b6001600160a01b031660009081526002602052604090206001015490565b6102dd6102ba366004611829565b6001600160a01b031660009081526002602052604090205465ffffffffffff1690565b60405165ffffffffffff909116815260200161025f565b6102dd65ffffffffffff81565b61035061030f366004611829565b6002602052600090815260409020805460019091015465ffffffffffff80831692600160301b810490911691600160601b9091046001600160a01b03169084565b6040805165ffffffffffff95861681529490931660208501526001600160a01b0390911691830191909152606082015260800161025f565b610255610396366004611844565b6106d0565b6102dd6106f3565b610255610703565b6103be6103b9366004611829565b610723565b005b6102556107f0565b61025533600090815260026020526040902054600160601b90046001600160a01b031690565b6102556103fc366004611829565b6001600160a01b03908116600090815260026020526040902054600160601b90041690565b6103be6107fb565b6104507f0000000000000000000000002c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a81565b6040516001600160a01b03909116815260200161025f565b61025561080f565b61025560035481565b61025560065481565b6103be610490366004611829565b610847565b6000546001600160a01b0316610450565b6103be6104b4366004611844565b6108ee565b610255610932565b6102556109fe565b6005546102dd90600160d01b900465ffffffffffff1681565b6102556104f0366004611844565b610a09565b3360009081526002602052604090205465ffffffffffff166102dd565b6005546102dd90600160a01b900465ffffffffffff1681565b6102dd610539366004611829565b610a1c565b610255610a80565b6103be61055436600461185d565b610a8b565b610255610567366004611829565b610b4e565b6103be61057a36600461185d565b610b8c565b6103be61058d366004611829565b610bec565b6103be6105a0366004611885565b610c27565b6102556105b3366004611829565b610cb7565b600554610450906001600160a01b031681565b6103be6105d9366004611829565b610ce6565b600454610450906001600160a01b031681565b6001600160a01b0381166000908152600260205260408120805465ffffffffffff1642116106225750600092915050565b805460055465ffffffffffff918216600160d01b9091049091161161064a5750600092915050565b600554600090600160d01b900465ffffffffffff1642116106805781546106799065ffffffffffff16426118c5565b90506106ac565b81546005546106a19165ffffffffffff90811691600160d01b9004166118d8565b65ffffffffffff1690505b81546106c890600160601b90046001600160a01b0316826118fe565b949350505050565b60006106da610d4e565b6106e382610d78565b90506106ee60018055565b919050565b60006106fe33610a1c565b905090565b600061070d610d4e565b61071561105b565b905061072060018055565b90565b61072b6111f9565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610772573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107969190611915565b90506107ac6001600160a01b0383163383611226565b60405181815233906001600160a01b038416907f4c9443772ec3472e2ea8a88e5c31e6bb75e94541dc672d5ca2a1197ada10b5989060200160405180910390a35050565b60006106fe336105f1565b6108036111f9565b61080d600061128a565b565b6000610819610d4e565b61071561084233600090815260026020526040902054600160601b90046001600160a01b031690565b610d78565b61084f610d4e565b6108576111f9565b6005546001600160a01b0316600061086d610932565b90508015610889576108896001600160a01b0383163383611226565b600580546001600160a01b0319166001600160a01b0385811691821790925560405183815290918416907fc133375757269458a329c73a344c8ef483535870f46ed4cd332f857a5ef525d09060200160405180910390a350506108eb60018055565b50565b6108f66111f9565b60068190556040518181527f929e0b2903ee7e8bb87bf220a340db1f5551e7042e5f2567ed08117c0709fa21906020015b60405180910390a150565b6005546000906001600160a01b031661094b5750600090565b6005546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b79190611915565b6005549091506001600160a01b039081167f0000000000000000000000002c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a90911603610720576003546106fe90826118c5565b60006106fe33610b4e565b6000610a13610d4e565b6106e3826112da565b6001600160a01b038082166000908152600260205260408120549091600160601b90910416610a515765ffffffffffff610a7a565b6001600160a01b038216600090815260026020526040902054600160301b900465ffffffffffff165b92915050565b60006106fe33610cb7565b610a936111f9565b60055442600160d01b90910465ffffffffffff1611610af95760405162461bcd60e51b815260206004820152601c60248201527f74696d652068617320746f20626520696e20746865206675747572650000000060448201526064015b60405180910390fd5b600580546001600160d01b0316600160d01b65ffffffffffff8416908102919091179091556040519081527fb8ec1a7db76539d0a932b67153298ec5ba41b1f965bd5f66e9419431d517291a90602001610927565b6005546000906001600160a01b03161580610b695750600654155b15610b7657506000919050565b600654610b8283610cb7565b610a7a919061192e565b610b946111f9565b6005805465ffffffffffff60a01b1916600160a01b65ffffffffffff8416908102919091179091556040519081527fe9f020bdf01408388704d87e8162e06252d160de9f8cc075b32ce7ebbebc263e90602001610927565b610bf46111f9565b6001600160a01b038116610c1e57604051631e4fbdf760e01b815260006004820152602401610af0565b6108eb8161128a565b610c2f6111f9565b6000610c3a83611523565b90508060010154821015610c675781816001016000828254610c5c91906118c5565b90915550610c6f9050565b600060018201555b826001600160a01b03167f33e88885e6abd26d1f3ea3b4b37c2f6e0ff31fa24c7721763eca867537bdf5d283604051610caa91815260200190565b60405180910390a2505050565b6001600160a01b038116600090815260026020526040812060010154610cdc836105f1565b610a7a9190611950565b610cee610d4e565b610cf66111f9565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f58ff585b99ade29efbc655970d10cfc8401e6ad7bf243459026c13271f88f79d90600090a3506108eb60018055565b600260015403610d7157604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b6000808211610dc95760405162461bcd60e51b815260206004820152601a60248201527f616d6f756e7420746f207769746864726177206e6f74203e20300000000000006044820152606401610af0565b610dd233610a1c565b65ffffffffffff164211610e285760405162461bcd60e51b815260206004820152601e60248201527f7374616b656420746f6b656e7320617265207374696c6c206c6f636b656400006044820152606401610af0565b600480546040516370a0823160e01b8152339281019290925283916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610e75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e999190611915565b1015610ee75760405162461bcd60e51b815260206004820152601860248201527f6e6f7420656e6f756768207374616b656420746f6b656e7300000000000000006044820152606401610af0565b6000610ef233611523565b8054909150600160601b90046001600160a01b0316831115610f565760405162461bcd60e51b815260206004820152601f60248201527f776974686472617720616d6f756e74203e207374616b656420616d6f756e74006044820152606401610af0565b610f5f83611584565b81548290600c90610f81908490600160601b90046001600160a01b0316611963565b92506101000a8154816001600160a01b0302191690836001600160a01b031602179055508260036000828254610fb791906118c5565b90915550610ff190506001600160a01b037f0000000000000000000000002c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a163385611226565b600454611009906001600160a01b03163330866115e1565b337ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5688461103542611620565b6040805192835265ffffffffffff90911660208301520160405180910390a25090919050565b6005546000906001600160a01b03166110b65760405162461bcd60e51b815260206004820152601860248201527f6e6f2072657761726420746f6b656e20636f6e747261637400000000000000006044820152606401610af0565b60006110c133610b4e565b9050600081116111085760405162461bcd60e51b81526020600482015260126024820152716e6f20746f6b656e7320746f20636c61696d60701b6044820152606401610af0565b336000908152600260205260408120600181019190915561112842611620565b815465ffffffffffff191665ffffffffffff91909116178155611149610932565b8211156111985760405162461bcd60e51b815260206004820152601860248201527f6e6f7420656e6f7567682072657761726420746f6b656e7300000000000000006044820152606401610af0565b6005546111af906001600160a01b03163384611226565b6005546040518381526001600160a01b039091169033907ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd39926839060200160405180910390a350919050565b6000546001600160a01b0316331461080d5760405163118cdaa760e01b8152336004820152602401610af0565b6040516001600160a01b0383811660248301526044820183905261128591859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611678565b505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080821161132b5760405162461bcd60e51b815260206004820152601860248201527f7374616b6520616d6f756e74206d757374206265203e203000000000000000006044820152606401610af0565b600480546040516370a0823160e01b8152309281019290925283916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139c9190611915565b10156113ea5760405162461bcd60e51b815260206004820152601e60248201527f7374616b696e67206c696d697420686173206265656e207265616368656400006044820152606401610af0565b60006113f533611523565b805490915061141e90611419908590600160601b90046001600160a01b0316611950565b611584565b81546001600160a01b0391909116600160601b026bffffffffffffffffffffffff9091161781556003805484919060009061145a908490611950565b90915550506005546114849061147f90600160a01b900465ffffffffffff1642611950565b611620565b815465ffffffffffff91909116600160301b026bffffffffffff000000000000199091161781556114e06001600160a01b037f0000000000000000000000002c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a163330866115e1565b6004546114f7906001600160a01b03163385611226565b337f5af417134f72a9d41143ace85b0a26dce6f550f894f2cbc1eeee8810603d91b68461103542611620565b6001600160a01b0381166000908152600260205260409020611544826105f1565b8160010160008282546115579190611950565b90915550611566905042611620565b815465ffffffffffff191665ffffffffffff91909116178155919050565b60006001600160a01b038211156115dd5760405162461bcd60e51b815260206004820152601d60248201527f76616c756520646f65736e27742066697420696e2031363020626974730000006044820152606401610af0565b5090565b6040516001600160a01b03848116602483015283811660448301526064820183905261161a9186918216906323b872dd90608401611253565b50505050565b600065ffffffffffff8211156115dd5760405162461bcd60e51b815260206004820152601c60248201527f76616c756520646f65736e27742066697420696e2034382062697473000000006044820152606401610af0565b600061168d6001600160a01b038416836116db565b905080516000141580156116b25750808060200190518101906116b09190611983565b155b1561128557604051635274afe760e01b81526001600160a01b0384166004820152602401610af0565b60606116e9838360006116f0565b9392505050565b6060814710156117155760405163cd78605960e01b8152306004820152602401610af0565b600080856001600160a01b0316848660405161173191906119a5565b60006040518083038185875af1925050503d806000811461176e576040519150601f19603f3d011682016040523d82523d6000602084013e611773565b606091505b509150915061178386838361178d565b9695505050505050565b6060826117a25761179d826117e9565b6116e9565b81511580156117b957506001600160a01b0384163b155b156117e257604051639996b31560e01b81526001600160a01b0385166004820152602401610af0565b50806116e9565b8051156117f95780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146106ee57600080fd5b60006020828403121561183b57600080fd5b6116e982611812565b60006020828403121561185657600080fd5b5035919050565b60006020828403121561186f57600080fd5b813565ffffffffffff811681146116e957600080fd5b6000806040838503121561189857600080fd5b6118a183611812565b946020939093013593505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610a7a57610a7a6118af565b65ffffffffffff8281168282160390808211156118f7576118f76118af565b5092915050565b8082028115828204841417610a7a57610a7a6118af565b60006020828403121561192757600080fd5b5051919050565b60008261194b57634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115610a7a57610a7a6118af565b6001600160a01b038281168282160390808211156118f7576118f76118af565b60006020828403121561199557600080fd5b815180151581146116e957600080fd5b6000825160005b818110156119c657602081860181015185830152016119ac565b50600092019182525091905056fea2646970667358221220a372cdf83ea862a7432ef748f49dc47df71de72f42e59ac0cb214300579760f464736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a000000000000000000000000da16444b8bd79618b7c7f73d898b025dc5a7f0950000000000000000000000002c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a000000000000000000000000000000000000000000000000000000000076a700
-----Decoded View---------------
Arg [0] : _stakingToken (address): 0x2C06BA9e7F0dACcbC1f6A33EA67e85bb68fbEE3a
Arg [1] : _governanceToken (address): 0xDA16444B8bd79618b7C7F73D898B025Dc5a7f095
Arg [2] : _rewardToken (address): 0x2C06BA9e7F0dACcbC1f6A33EA67e85bb68fbEE3a
Arg [3] : _lockTimePeriod (uint48): 7776000
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000002c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a
Arg [1] : 000000000000000000000000da16444b8bd79618b7c7f73d898b025dc5a7f095
Arg [2] : 0000000000000000000000002c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a
Arg [3] : 000000000000000000000000000000000000000000000000000000000076a700
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.