More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 318 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw Vested ... | 22202103 | 17 days ago | IN | 0 ETH | 0.00003963 | ||||
Withdraw Vested ... | 22149758 | 25 days ago | IN | 0 ETH | 0.00004242 | ||||
Withdraw | 22101383 | 31 days ago | IN | 0 ETH | 0.00002998 | ||||
Withdraw | 22044404 | 39 days ago | IN | 0 ETH | 0.0000781 | ||||
Withdraw Vested ... | 21837028 | 68 days ago | IN | 0 ETH | 0.00013573 | ||||
Withdraw | 21712655 | 86 days ago | IN | 0 ETH | 0.00064994 | ||||
Withdraw | 21712649 | 86 days ago | IN | 0 ETH | 0.00068308 | ||||
Withdraw Vested ... | 21691763 | 89 days ago | IN | 0 ETH | 0.00139683 | ||||
Vest | 21691762 | 89 days ago | IN | 0 ETH | 0.0006019 | ||||
Withdraw Vested ... | 21691757 | 89 days ago | IN | 0 ETH | 0.00131481 | ||||
Vest | 21691756 | 89 days ago | IN | 0 ETH | 0.00062984 | ||||
Withdraw | 21574199 | 105 days ago | IN | 0 ETH | 0.00155334 | ||||
Withdraw | 21528176 | 112 days ago | IN | 0 ETH | 0.00064901 | ||||
Vest | 21505176 | 115 days ago | IN | 0 ETH | 0.00034003 | ||||
Withdraw | 21505170 | 115 days ago | IN | 0 ETH | 0.00028194 | ||||
Withdraw | 21505092 | 115 days ago | IN | 0 ETH | 0.00035507 | ||||
Vest | 21501614 | 115 days ago | IN | 0 ETH | 0.00052785 | ||||
Withdraw | 21497599 | 116 days ago | IN | 0 ETH | 0.00044704 | ||||
Withdraw | 21490603 | 117 days ago | IN | 0 ETH | 0.00055443 | ||||
Vest | 21490591 | 117 days ago | IN | 0 ETH | 0.00053501 | ||||
Withdraw | 21489956 | 117 days ago | IN | 0 ETH | 0.00038126 | ||||
Vest | 21489930 | 117 days ago | IN | 0 ETH | 0.00064133 | ||||
Withdraw | 21489157 | 117 days ago | IN | 0 ETH | 0.00052414 | ||||
Stake | 21479067 | 118 days ago | IN | 0 ETH | 0.00048064 | ||||
Vest | 21476404 | 119 days ago | IN | 0 ETH | 0.00041962 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
StablecoinFarm
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import { Pausable } from '../Pausable.sol'; import { BalanceManagement } from '../BalanceManagement.sol'; import { IRevenueShare } from '../interfaces/IRevenueShare.sol'; contract StablecoinFarm is Pausable, BalanceManagement { using SafeERC20 for IERC20; struct VestedBalance { uint256 amount; uint256 unlockTime; } // Info of each user. struct UserInfo { uint256 amount; // How many tokens the user has provided. uint256 rewardDebt; // Reward debt. See the explanation below. uint256 remainingRewardTokenAmount; // Tokens that weren't distributed for a user per pool. // Any point in time, the amount of reward tokens entitled to a user but pending to be distributed is: // pending reward = (user.amount * pool.accumulatedRewardTokenPerShare) - user.rewardDebt // // Whenever a user deposits or withdraws Staked tokens to a pool. Here's what happens: // 1. The pool's `accumulatedRewardTokenPerShare` (and `lastRewardTime`) gets updated. // 2. A user receives the pending reward sent to his/her address. // 3. The user's `amount` gets updated. // 4. The user's `rewardDebt` gets updated. } // Info of each pool. struct PoolInfo { address stakingToken; // Contract address of staked token uint256 stakingTokenTotalAmount; //Total amount of deposited tokens uint256 accumulatedRewardTokenPerShare; // Accumulated reward token per share, times 1e12. See below. uint32 lastRewardTime; // Last timestamp number that reward token distribution occurs. uint16 allocationPoint; // How many allocation points are assigned to this pool. } address public immutable rewardToken; // The reward token. address public treasury; // The penalty address of the treasury. address public LPRevenueShare; // The penalty address of the fee LPRevenueShare contract. uint256 public rewardTokenPerSecond; // Reward tokens vested per second. PoolInfo[] public poolInfo; // Info of each pool. mapping(address => bool) public isStakingTokenSet; mapping(uint256 => mapping(address => UserInfo)) public userInfo; // Info of each user that stakes tokens. mapping(uint256 => mapping(address => VestedBalance[])) public userVested; // vested tokens uint256 public totalAllocationPoint = 0; // the sum of all allocation points in all pools. uint32 public immutable startTime; // the timestamp when reward token farming starts. uint32 public endTime; // time on which the reward calculation should end. uint256 public immutable vestingDuration; uint256 public exitEarlyUserShare = 500; // 50% uint256 public exitEarlyTreasuryShare = 200; // 20% uint256 public exitEarlyLPShare = 300; // 30% // Factor to perform multiplication and division operations. uint256 private constant SHARE_PRECISION = 1e18; event Staked(address indexed user, uint256 indexed pid, uint256 amount); event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount); event WithdrawVesting(address indexed user, uint256 amount); event Vested(address indexed user, uint256 indexed pid, uint256 amount); event Locked(address indexed user, uint256 indexed pid, uint256 amount); event ExitEarly(address indexed user, uint256 amount); constructor( address _rewardToken, uint256 _rewardTokenPerSecond, uint32 _startTime, uint256 _vestingDuration ) { rewardToken = _rewardToken; rewardTokenPerSecond = _rewardTokenPerSecond; startTime = _startTime; endTime = startTime + 90 days; vestingDuration = _vestingDuration; } /** * @dev Sets a new treasury * @param _newTreasury is a new treasury address */ function setTreasury(address _newTreasury) external onlyOwner { require(_newTreasury != address(0), 'Zero address error'); treasury = _newTreasury; } /** * @dev Sets a new LP revenue share * @param _newRevenueShare is a new LP revenue share address */ function setLPRevenueShare(address _newRevenueShare) external onlyOwner { require(_newRevenueShare != address(0), 'Zero address error'); LPRevenueShare = _newRevenueShare; } /** * @dev Sets portions for exit early. If it needs to set 33.3%, just provide a 333 value. * Pay attention, the sum of all values must be 1000, which means 100% * @param _userPercent is a user percent * @param _treasuryPercent is a treasury percent * @param _lpPercent is an LP share percent */ function setPercentsShare( uint256 _userPercent, uint256 _treasuryPercent, uint256 _lpPercent ) external onlyOwner { require( _userPercent + _treasuryPercent + _lpPercent == 1000, 'Total percentage should be 100% in total' ); exitEarlyUserShare = _userPercent; exitEarlyTreasuryShare = _treasuryPercent; exitEarlyLPShare = _lpPercent; } /** * @dev Deposit staking tokens for reward token allocation. * @param _pid is a pool id * @param _amount is a number of deposit tokens */ function stake(uint256 _pid, uint256 _amount) external whenNotPaused { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; _updatePool(_pid); IERC20(pool.stakingToken).safeTransferFrom(msg.sender, address(this), _amount); user.remainingRewardTokenAmount = pendingRewardToken(_pid, msg.sender); user.amount += _amount; pool.stakingTokenTotalAmount += _amount; user.rewardDebt = (user.amount * pool.accumulatedRewardTokenPerShare) / SHARE_PRECISION; emit Staked(msg.sender, _pid, _amount); } /** * @dev Withdraw only staked iUSDC/iUSDT tokens * @param _pid is a pool id * @param _amount is an amount of withdrawn tokens */ function withdraw(uint256 _pid, uint256 _amount) external whenNotPaused { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; if (user.amount < _amount) { revert('Can not withdraw this amount'); } _updatePool(_pid); user.remainingRewardTokenAmount = pendingRewardToken(_pid, msg.sender); user.amount -= _amount; pool.stakingTokenTotalAmount -= _amount; user.rewardDebt = (user.amount * pool.accumulatedRewardTokenPerShare) / SHARE_PRECISION; IERC20(pool.stakingToken).safeTransfer(msg.sender, _amount); emit Withdraw(msg.sender, _pid, _amount); } /** * @dev Withdraw without caring about rewards. EMERGENCY ONLY. * @param _pid is a pool id */ function emergencyWithdraw(uint256 _pid) external { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; uint256 userAmount = user.amount; pool.stakingTokenTotalAmount -= userAmount; user.amount = 0; user.rewardDebt = 0; user.remainingRewardTokenAmount = 0; IERC20(pool.stakingToken).safeTransfer(msg.sender, userAmount); emit EmergencyWithdraw(msg.sender, _pid, userAmount); } /** * @dev Add seconds to endTime parameter * @param _addSeconds is an additional seconds value */ function changeEndTime(uint32 _addSeconds) external onlyManager { endTime += _addSeconds; } /** * @dev Changes reward token amount per second. Use this function to moderate the `lockup amount`. * Essentially this function changes the amount of the reward which is entitled to the user * for his token staking by the time the `endTime` is passed. * Good practice to update pools without messing up the contract. * @param _rewardTokenPerSecond is a new value for reward token per second * @param _withUpdate if set in true all pools will be updated, * otherwise only new rewardTokenPerSecond will be set */ function setRewardTokenPerSecond( uint256 _rewardTokenPerSecond, bool _withUpdate ) external onlyManager { if (_withUpdate) { _massUpdatePools(); } rewardTokenPerSecond = _rewardTokenPerSecond; } /** * @dev Add a new staking token to the pool. Can only be called by managers. * @param _allocPoint is an allocation point * @param _stakingToken is a staked token address that will be used for the new pool * @param _withUpdate if set in true all pools will be updated, * otherwise only the new pool will be added */ function add(uint16 _allocPoint, address _stakingToken, bool _withUpdate) external onlyManager { require(!isStakingTokenSet[_stakingToken], 'Staking token was already set'); require(poolInfo.length < 5, 'No more then 5 pools can be added'); if (_withUpdate) { _massUpdatePools(); } uint256 lastRewardTime = block.timestamp > startTime ? block.timestamp : startTime; totalAllocationPoint += _allocPoint; poolInfo.push( PoolInfo({ stakingToken: _stakingToken, stakingTokenTotalAmount: 0, allocationPoint: _allocPoint, lastRewardTime: uint32(lastRewardTime), accumulatedRewardTokenPerShare: 0 }) ); isStakingTokenSet[_stakingToken] = true; } /** * @dev Update the given pool's reward token allocation point. Can only be called by managers. * @param _pid is a pool id that exists in the list * @param _allocPoint is an allocation point * @param _withUpdate if set in true all pools will be updated, * otherwise only allocation data will be updated */ function set(uint256 _pid, uint16 _allocPoint, bool _withUpdate) external onlyManager { if (_withUpdate) { _massUpdatePools(); } totalAllocationPoint = totalAllocationPoint - poolInfo[_pid].allocationPoint + _allocPoint; poolInfo[_pid].allocationPoint = _allocPoint; } /** * @dev Update reward variables for all pools. */ function massUpdatePools() external whenNotPaused { _massUpdatePools(); } /** * @dev Update reward variables of the given pool to be up-to-date. */ function updatePool(uint256 _pid) external whenNotPaused { _updatePool(_pid); } /** * @dev How many pools are in the contract */ function poolLength() external view returns (uint256) { return poolInfo.length; } /** * @dev Vest all pending rewards. Vest tokens means that they will be locked for the * vestingDuration time * @param _pid is a pool id */ function vest(uint256 _pid) external whenNotPaused { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; _updatePool(_pid); uint256 pending = pendingRewardToken(_pid, msg.sender); require(pending > 0, 'Amount of tokens can not be zero value'); uint256 unlockTime = block.timestamp + vestingDuration; VestedBalance[] storage vestings = userVested[_pid][msg.sender]; require(vestings.length <= 100, 'User can not execute vest function more than 100 times'); vestings.push(VestedBalance({ amount: pending, unlockTime: unlockTime })); user.remainingRewardTokenAmount = 0; user.rewardDebt = (user.amount * pool.accumulatedRewardTokenPerShare) / SHARE_PRECISION; emit Vested(msg.sender, _pid, pending); } /** * @dev user can get his rewards for staked iUSDC/iUSDT if locked time has already occurred * @param _pid is a pool id */ function withdrawVestedRewards(uint256 _pid) external { // withdraw only `vestedTotal` amount _updatePool(_pid); (uint256 vested, , ) = checkVestingBalances(_pid, msg.sender); uint256 amount; if (vested > 0) { uint256 length = userVested[_pid][msg.sender].length; for (uint256 i = 0; i < length; i++) { uint256 vestAmount = userVested[_pid][msg.sender][i].amount; if (userVested[_pid][msg.sender][i].unlockTime > block.timestamp) { break; } amount = amount + vestAmount; delete userVested[_pid][msg.sender][i]; } } if (amount > 0) { safeRewardTransfer(msg.sender, amount); } else { revert('Tokens are not available for now'); } emit WithdrawVesting(msg.sender, amount); } /** * @dev The user receives only `exitEarlyUserShare` - 50% tokens by default * `exitEarlyTreasuryShare` - 20% tokens by default transfers to the treasury account * `exitEarlyLPShare` - 30% tokens by default transfers to the LP revenue share contract * @param _pid is a pool id */ function exitEarly(uint256 _pid) external { _updatePool(_pid); // can withdraw 50% immediately (, uint256 vesting, ) = checkVestingBalances(_pid, msg.sender); require(vesting > 0, 'Total vesting tokens can not be zero'); uint256 amountUser = (vesting * exitEarlyUserShare) / 1000; uint256 amountTreasury = (vesting * exitEarlyTreasuryShare) / 1000; uint256 amountLP = (vesting * exitEarlyLPShare) / 1000; safeRewardTransfer(msg.sender, amountUser); // transfer penalties IERC20(rewardToken).safeTransfer(treasury, amountTreasury); IERC20(rewardToken).safeTransfer(LPRevenueShare, amountLP); _cleanVestingBalances(_pid, msg.sender); emit ExitEarly(msg.sender, amountUser); } /** * @dev Unsupported operation * @param _pid is a pool id */ function lockVesting(uint256 _pid) external { revert('Unsupported operation'); } /** * @dev Unsupported operation * @param _pid is a pool id */ function lockPending(uint256 _pid) external { revert('Unsupported operation'); } /** * @dev Return reward multiplier over the given _from to _to time. * @param _from is a from datetime in seconds * @param _to is a to datetime in seconds * @return multiplier */ function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) { _from = _from > startTime ? _from : startTime; if (_from > endTime || _to < startTime) { return 0; } else if (_to > endTime) { return endTime - _from; } else return _to - _from; } /** * @dev Check if provided token is staked token in the pool * @param _tokenAddress is a checked token * @return result true if provided token is staked token in the pool, otherwise false */ function isReservedToken(address _tokenAddress) public view override returns (bool) { uint256 length = poolInfo.length; for (uint256 pid; pid < length; ++pid) { if (_tokenAddress == poolInfo[pid].stakingToken) { return true; } } return false; } /** * @dev View function to see pending reward tokens on the frontend. * @param _pid is a pool id * @param _user is a user address to check rewards * @return pending reward token amount */ function pendingRewardToken(uint256 _pid, address _user) public view returns (uint256 pending) { PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_user]; uint256 acc = pool.accumulatedRewardTokenPerShare; if (block.timestamp > pool.lastRewardTime && pool.stakingTokenTotalAmount != 0) { uint256 multiplier = getMultiplier(pool.lastRewardTime, block.timestamp); uint256 tokenReward = (multiplier * rewardTokenPerSecond * pool.allocationPoint) / totalAllocationPoint; acc += (tokenReward * SHARE_PRECISION) / pool.stakingTokenTotalAmount; } pending = (user.amount * acc) / SHARE_PRECISION - user.rewardDebt + user.remainingRewardTokenAmount; } /** * @dev Information on a user's total/vestedTotal/vestingTotal balances * @param _pid is a pool id * @param _user is a user address to check rewards * @return vestedTotal is the number of vested tokens (that are available to withdraw) * @return vestingTotal is the number of vesting tokens (that are not available to withdraw yet) * @return vestData is the list with the number of tokens and their unlock time */ function checkVestingBalances( uint256 _pid, address _user ) public view returns ( uint256 vestedTotal, // available to withdraw uint256 vestingTotal, VestedBalance[] memory vestData ) { VestedBalance[] storage vests = userVested[_pid][_user]; uint256 index; for (uint256 i = 0; i < vests.length; i++) { if (vests[i].unlockTime > block.timestamp) { if (index == 0) { vestData = new VestedBalance[](vests.length - i); } vestData[index] = vests[i]; index++; vestingTotal += vests[i].amount; } else { vestedTotal = vestedTotal + vests[i].amount; } } } function _cleanVestingBalances(uint256 _pid, address _user) internal { VestedBalance[] storage vests = userVested[_pid][_user]; for (uint256 i = 0; i < vests.length; i++) { if (vests[i].unlockTime > block.timestamp) { delete vests[i]; } } } /** * @dev Safe reward token transfer function. * Revert error if not enough tokens on the smart contract * Just in case the pool does not have enough reward tokens. * @param _to is an address to transfer rewards * @param _amount is a number of reward tokens that will be transferred to the user */ function safeRewardTransfer(address _to, uint256 _amount) private { uint256 rewardTokenBalance = IERC20(rewardToken).balanceOf(address(this)); if (_amount > rewardTokenBalance) { revert('Not enough tokens on the smart contract'); } else { IERC20(rewardToken).safeTransfer(_to, _amount); } } /** * @dev Update reward variables for all pools */ function _massUpdatePools() private { uint256 length = poolInfo.length; for (uint256 pid; pid < length; ++pid) { _updatePool(pid); } } /** * @dev Update reward variables of the given pool to be up-to-date. * @param _pid is a pool id */ function _updatePool(uint256 _pid) private { PoolInfo storage pool = poolInfo[_pid]; if (block.timestamp <= pool.lastRewardTime) { return; } if (pool.stakingTokenTotalAmount == 0) { pool.lastRewardTime = uint32(block.timestamp); return; } uint256 multiplier = getMultiplier(pool.lastRewardTime, block.timestamp); uint256 rewardTokenAmount = (multiplier * rewardTokenPerSecond * pool.allocationPoint) / totalAllocationPoint; pool.accumulatedRewardTokenPerShare += (rewardTokenAmount * SHARE_PRECISION) / pool.stakingTokenTotalAmount; pool.lastRewardTime = uint32(block.timestamp); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../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. * * By default, the owner account will be the one that deploys the contract. 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; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @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 { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing 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 { require(newOwner != address(0), "Ownable: new owner is the zero address"); _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 v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @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. */ 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]. */ 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 v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @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 amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` 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 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../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; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @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://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @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, it is bubbled up by this * function (like regular Solidity function calls). * * 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. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @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`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { ITokenBalance } from './interfaces/ITokenBalance.sol'; import { ManagerRole } from './roles/ManagerRole.sol'; import './helpers/TransferHelper.sol' as TransferHelper; import './Constants.sol' as Constants; /** * @title BalanceManagement * @notice Base contract for the withdrawal of tokens, except for reserved ones */ abstract contract BalanceManagement is ManagerRole { /** * @notice Emitted when the specified token is reserved */ error ReservedTokenError(); /** * @notice Performs the withdrawal of tokens, except for reserved ones * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token * @param _tokenAddress The address of the token * @param _tokenAmount The amount of the token */ function cleanup(address _tokenAddress, uint256 _tokenAmount) external onlyManager { if (isReservedToken(_tokenAddress)) { revert ReservedTokenError(); } if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { TransferHelper.safeTransferNative(msg.sender, _tokenAmount); } else { TransferHelper.safeTransfer(_tokenAddress, msg.sender, _tokenAmount); } } /** * @notice Getter of the token balance of the current contract * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token * @param _tokenAddress The address of the token * @return The token balance of the current contract */ function tokenBalance(address _tokenAddress) public view returns (uint256) { if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { return address(this).balance; } else { return ITokenBalance(_tokenAddress).balanceOf(address(this)); } } /** * @notice Getter of the reserved token flag * @dev Override to add reserved token addresses * @param _tokenAddress The address of the token * @return The reserved token flag */ function isReservedToken(address _tokenAddress) public view virtual returns (bool) { // The function returns false by default. // The explicit return statement is omitted to avoid the unused parameter warning. // See https://github.com/ethereum/solidity/issues/5295 } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @dev The default token decimals value */ uint256 constant DECIMALS_DEFAULT = 18; /** * @dev The maximum uint256 value for swap amount limit settings */ uint256 constant INFINITY = type(uint256).max; /** * @dev The default limit of account list size */ uint256 constant LIST_SIZE_LIMIT_DEFAULT = 100; /** * @dev The limit of swap router list size */ uint256 constant LIST_SIZE_LIMIT_ROUTERS = 200; /** * @dev The factor for percentage settings. Example: 100 is 0.1% */ uint256 constant MILLIPERCENT_FACTOR = 100_000; /** * @dev The de facto standard address to denote the native token */ address constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Optional value structure * @dev Is used in mappings to allow zero values * @param isSet Value presence flag * @param value Numeric value */ struct OptionalValue { bool isSet; uint256 value; } /** * @notice Key-to-value structure * @dev Is used as an array parameter item to perform multiple key-value settings * @param key Numeric key * @param value Numeric value */ struct KeyToValue { uint256 key; uint256 value; } /** * @notice Key-to-value structure for address values * @dev Is used as an array parameter item to perform multiple key-value settings with address values * @param key Numeric key * @param value Address value */ struct KeyToAddressValue { uint256 key; address value; } /** * @notice Address-to-flag structure * @dev Is used as an array parameter item to perform multiple settings * @param account Account address * @param flag Flag value */ struct AccountToFlag { address account; bool flag; } /** * @notice Emitted when a list exceeds the size limit */ error ListSizeLimitError(); /** * @notice Sets or updates a value in a combined map (a mapping with a key list and key index mapping) * @param _map The mapping reference * @param _keyList The key list reference * @param _keyIndexMap The key list index mapping reference * @param _key The numeric key * @param _value The address value * @param _sizeLimit The map and list size limit * @return isNewKey True if the key was just added, otherwise false */ function combinedMapSet( mapping(uint256 => address) storage _map, uint256[] storage _keyList, mapping(uint256 => OptionalValue) storage _keyIndexMap, uint256 _key, address _value, uint256 _sizeLimit ) returns (bool isNewKey) { isNewKey = !_keyIndexMap[_key].isSet; if (isNewKey) { uniqueListAdd(_keyList, _keyIndexMap, _key, _sizeLimit); } _map[_key] = _value; } /** * @notice Removes a value from a combined map (a mapping with a key list and key index mapping) * @param _map The mapping reference * @param _keyList The key list reference * @param _keyIndexMap The key list index mapping reference * @param _key The numeric key * @return isChanged True if the combined map was changed, otherwise false */ function combinedMapRemove( mapping(uint256 => address) storage _map, uint256[] storage _keyList, mapping(uint256 => OptionalValue) storage _keyIndexMap, uint256 _key ) returns (bool isChanged) { isChanged = _keyIndexMap[_key].isSet; if (isChanged) { delete _map[_key]; uniqueListRemove(_keyList, _keyIndexMap, _key); } } /** * @notice Adds a value to a unique value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The numeric value * @param _sizeLimit The list size limit * @return isChanged True if the list was changed, otherwise false */ function uniqueListAdd( uint256[] storage _list, mapping(uint256 => OptionalValue) storage _indexMap, uint256 _value, uint256 _sizeLimit ) returns (bool isChanged) { isChanged = !_indexMap[_value].isSet; if (isChanged) { if (_list.length >= _sizeLimit) { revert ListSizeLimitError(); } _indexMap[_value] = OptionalValue(true, _list.length); _list.push(_value); } } /** * @notice Removes a value from a unique value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The numeric value * @return isChanged True if the list was changed, otherwise false */ function uniqueListRemove( uint256[] storage _list, mapping(uint256 => OptionalValue) storage _indexMap, uint256 _value ) returns (bool isChanged) { OptionalValue storage indexItem = _indexMap[_value]; isChanged = indexItem.isSet; if (isChanged) { uint256 itemIndex = indexItem.value; uint256 lastIndex = _list.length - 1; if (itemIndex != lastIndex) { uint256 lastValue = _list[lastIndex]; _list[itemIndex] = lastValue; _indexMap[lastValue].value = itemIndex; } _list.pop(); delete _indexMap[_value]; } } /** * @notice Adds a value to a unique address value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The address value * @param _sizeLimit The list size limit * @return isChanged True if the list was changed, otherwise false */ function uniqueAddressListAdd( address[] storage _list, mapping(address => OptionalValue) storage _indexMap, address _value, uint256 _sizeLimit ) returns (bool isChanged) { isChanged = !_indexMap[_value].isSet; if (isChanged) { if (_list.length >= _sizeLimit) { revert ListSizeLimitError(); } _indexMap[_value] = OptionalValue(true, _list.length); _list.push(_value); } } /** * @notice Removes a value from a unique address value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The address value * @return isChanged True if the list was changed, otherwise false */ function uniqueAddressListRemove( address[] storage _list, mapping(address => OptionalValue) storage _indexMap, address _value ) returns (bool isChanged) { OptionalValue storage indexItem = _indexMap[_value]; isChanged = indexItem.isSet; if (isChanged) { uint256 itemIndex = indexItem.value; uint256 lastIndex = _list.length - 1; if (itemIndex != lastIndex) { address lastValue = _list[lastIndex]; _list[itemIndex] = lastValue; _indexMap[lastValue].value = itemIndex; } _list.pop(); delete _indexMap[_value]; } } /** * @notice Adds or removes a value to/from a unique address value list (a list with value index mapping) * @dev The list size limit is checked on items adding only * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The address value * @param _flag The value inclusion flag * @param _sizeLimit The list size limit * @return isChanged True if the list was changed, otherwise false */ function uniqueAddressListUpdate( address[] storage _list, mapping(address => OptionalValue) storage _indexMap, address _value, bool _flag, uint256 _sizeLimit ) returns (bool isChanged) { return _flag ? uniqueAddressListAdd(_list, _indexMap, _value, _sizeLimit) : uniqueAddressListRemove(_list, _indexMap, _value); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Emitted when an approval action fails */ error SafeApproveError(); /** * @notice Emitted when a transfer action fails */ error SafeTransferError(); /** * @notice Emitted when a transferFrom action fails */ error SafeTransferFromError(); /** * @notice Emitted when a transfer of the native token fails */ error SafeTransferNativeError(); /** * @notice Safely approve the token to the account * @param _token The token address * @param _to The token approval recipient address * @param _value The token approval amount */ function safeApprove(address _token, address _to, uint256 _value) { // 0x095ea7b3 is the selector for "approve(address,uint256)" (bool success, bytes memory data) = _token.call( abi.encodeWithSelector(0x095ea7b3, _to, _value) ); bool condition = success && (data.length == 0 || abi.decode(data, (bool))); if (!condition) { revert SafeApproveError(); } } /** * @notice Safely transfer the token to the account * @param _token The token address * @param _to The token transfer recipient address * @param _value The token transfer amount */ function safeTransfer(address _token, address _to, uint256 _value) { // 0xa9059cbb is the selector for "transfer(address,uint256)" (bool success, bytes memory data) = _token.call( abi.encodeWithSelector(0xa9059cbb, _to, _value) ); bool condition = success && (data.length == 0 || abi.decode(data, (bool))); if (!condition) { revert SafeTransferError(); } } /** * @notice Safely transfer the token between the accounts * @param _token The token address * @param _from The token transfer source address * @param _to The token transfer recipient address * @param _value The token transfer amount */ function safeTransferFrom(address _token, address _from, address _to, uint256 _value) { // 0x23b872dd is the selector for "transferFrom(address,address,uint256)" (bool success, bytes memory data) = _token.call( abi.encodeWithSelector(0x23b872dd, _from, _to, _value) ); bool condition = success && (data.length == 0 || abi.decode(data, (bool))); if (!condition) { revert SafeTransferFromError(); } } /** * @notice Safely transfer the native token to the account * @param _to The native token transfer recipient address * @param _value The native token transfer amount */ function safeTransferNative(address _to, uint256 _value) { (bool success, ) = _to.call{ value: _value }(new bytes(0)); if (!success) { revert SafeTransferNativeError(); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; /** * @title IRevenueShare * @notice Revenue share interface */ interface IRevenueShare { /** * @notice Withdraws tokens */ function withdraw() external; /** * @notice Locks tokens * @param _amount The number of tokens to lock */ function lock(uint256 _amount) external; /** * @notice Locks tokens on behalf of the user * @param _amount The number of tokens to lock * @param _user The address of the user */ function lock(uint256 _amount, address _user) external; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title ITokenBalance * @notice Token balance interface */ interface ITokenBalance { /** * @notice Getter of the token balance by the account * @param _account The account address * @return Token balance */ function balanceOf(address _account) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { Pausable as PausableBase } from '@openzeppelin/contracts/security/Pausable.sol'; import { ManagerRole } from './roles/ManagerRole.sol'; /** * @title Pausable * @notice Base contract that implements the emergency pause mechanism */ abstract contract Pausable is PausableBase, ManagerRole { /** * @notice Enter pause state */ function pause() external onlyManager whenNotPaused { _pause(); } /** * @notice Exit pause state */ function unpause() external onlyManager whenPaused { _unpause(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol'; import { RoleBearers } from './RoleBearers.sol'; /** * @title ManagerRole * @notice Base contract that implements the Manager role. * The manager role is a high-permission role for core team members only. * Managers can set vaults and routers addresses, fees, cross-chain protocols, * and other parameters for Interchain (cross-chain) swaps and single-network swaps. * Please note, the manager role is unique for every contract, * hence different addresses may be assigned as managers for different contracts. */ abstract contract ManagerRole is Ownable, RoleBearers { bytes32 private constant ROLE_KEY = keccak256('Manager'); /** * @notice Emitted when the Manager role status for the account is updated * @param account The account address * @param value The Manager role status flag */ event SetManager(address indexed account, bool indexed value); /** * @notice Emitted when the Manager role status for the account is renounced * @param account The account address */ event RenounceManagerRole(address indexed account); /** * @notice Emitted when the caller is not a Manager role bearer */ error OnlyManagerError(); /** * @dev Modifier to check if the caller is a Manager role bearer */ modifier onlyManager() { if (!isManager(msg.sender)) { revert OnlyManagerError(); } _; } /** * @notice Updates the Manager role status for the account * @param _account The account address * @param _value The Manager role status flag */ function setManager(address _account, bool _value) public onlyOwner { _setRoleBearer(ROLE_KEY, _account, _value); emit SetManager(_account, _value); } /** * @notice Renounces the Manager role */ function renounceManagerRole() external onlyManager { _setRoleBearer(ROLE_KEY, msg.sender, false); emit RenounceManagerRole(msg.sender); } /** * @notice Getter of the Manager role bearer count * @return The Manager role bearer count */ function managerCount() external view returns (uint256) { return _roleBearerCount(ROLE_KEY); } /** * @notice Getter of the complete list of the Manager role bearers * @return The complete list of the Manager role bearers */ function fullManagerList() external view returns (address[] memory) { return _fullRoleBearerList(ROLE_KEY); } /** * @notice Getter of the Manager role bearer status * @param _account The account address */ function isManager(address _account) public view returns (bool) { return _isRoleBearer(ROLE_KEY, _account); } function _initRoles( address _owner, address[] memory _managers, bool _addOwnerToManagers ) internal { address ownerAddress = _owner == address(0) ? msg.sender : _owner; for (uint256 index; index < _managers.length; index++) { setManager(_managers[index], true); } if (_addOwnerToManagers && !isManager(ownerAddress)) { setManager(ownerAddress, true); } if (ownerAddress != msg.sender) { transferOwnership(ownerAddress); } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import '../Constants.sol' as Constants; import '../DataStructures.sol' as DataStructures; /** * @title RoleBearers * @notice Base contract that implements role-based access control * @dev A custom implementation providing full role bearer lists */ abstract contract RoleBearers { mapping(bytes32 /*roleKey*/ => address[] /*roleBearers*/) private roleBearerTable; mapping(bytes32 /*roleKey*/ => mapping(address /*account*/ => DataStructures.OptionalValue /*status*/)) private roleBearerIndexTable; function _setRoleBearer(bytes32 _roleKey, address _account, bool _value) internal { DataStructures.uniqueAddressListUpdate( roleBearerTable[_roleKey], roleBearerIndexTable[_roleKey], _account, _value, Constants.LIST_SIZE_LIMIT_DEFAULT ); } function _isRoleBearer(bytes32 _roleKey, address _account) internal view returns (bool) { return roleBearerIndexTable[_roleKey][_account].isSet; } function _roleBearerCount(bytes32 _roleKey) internal view returns (uint256) { return roleBearerTable[_roleKey].length; } function _fullRoleBearerList(bytes32 _roleKey) internal view returns (address[] memory) { return roleBearerTable[_roleKey]; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_rewardTokenPerSecond","type":"uint256"},{"internalType":"uint32","name":"_startTime","type":"uint32"},{"internalType":"uint256","name":"_vestingDuration","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ListSizeLimitError","type":"error"},{"inputs":[],"name":"OnlyManagerError","type":"error"},{"inputs":[],"name":"ReservedTokenError","type":"error"},{"inputs":[],"name":"SafeTransferError","type":"error"},{"inputs":[],"name":"SafeTransferNativeError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExitEarly","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Locked","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"RenounceManagerRole","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"SetManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Vested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawVesting","type":"event"},{"inputs":[],"name":"LPRevenueShare","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_allocPoint","type":"uint16"},{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_addSeconds","type":"uint32"}],"name":"changeEndTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"checkVestingBalances","outputs":[{"internalType":"uint256","name":"vestedTotal","type":"uint256"},{"internalType":"uint256","name":"vestingTotal","type":"uint256"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"internalType":"struct StablecoinFarm.VestedBalance[]","name":"vestData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"cleanup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"exitEarly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exitEarlyLPShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exitEarlyTreasuryShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exitEarlyUserShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullManagerList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_from","type":"uint256"},{"internalType":"uint256","name":"_to","type":"uint256"}],"name":"getMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"isReservedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isStakingTokenSet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"lockPending","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"lockVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"managerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingRewardToken","outputs":[{"internalType":"uint256","name":"pending","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"address","name":"stakingToken","type":"address"},{"internalType":"uint256","name":"stakingTokenTotalAmount","type":"uint256"},{"internalType":"uint256","name":"accumulatedRewardTokenPerShare","type":"uint256"},{"internalType":"uint32","name":"lastRewardTime","type":"uint32"},{"internalType":"uint16","name":"allocationPoint","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceManagerRole","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":[],"name":"rewardTokenPerSecond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint16","name":"_allocPoint","type":"uint16"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newRevenueShare","type":"address"}],"name":"setLPRevenueShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_userPercent","type":"uint256"},{"internalType":"uint256","name":"_treasuryPercent","type":"uint256"},{"internalType":"uint256","name":"_lpPercent","type":"uint256"}],"name":"setPercentsShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_rewardTokenPerSecond","type":"uint256"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"setRewardTokenPerSecond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newTreasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"tokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAllocationPoint","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":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"uint256","name":"remainingRewardTokenAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userVested","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"vest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vestingDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"withdrawVestedRewards","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e06040526000600a556101f4600c5560c8600d5561012c600e553480156200002757600080fd5b5060405162003102380380620031028339810160408190526200004a916200010c565b6000805460ff191690556200005f33620000b3565b6001600160a01b038416608052600583905563ffffffff821660a08190526200008c906276a7006200016d565b600b805463ffffffff191663ffffffff9290921691909117905560c05250620001a0915050565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b600080600080608085870312156200012357600080fd5b84516001600160a01b03811681146200013b57600080fd5b60208601516040870151919550935063ffffffff811681146200015d57600080fd5b6060959095015193969295505050565b63ffffffff8181168382160190808211156200019957634e487b7160e01b600052601160045260246000fd5b5092915050565b60805160a05160c051612eec6200021660003960008181610335015261125e0152600081816105060152818161154901528181611576015281816115b80152818161179a01526117c701526000818161073601528181610c5301528181610c8d015281816120ea01526121cc0152612eec6000f3fe608060405234801561001057600080fd5b50600436106102d65760003560e01c80638da5cb5b11610182578063cf42947b116100e9578063e859c0b5116100a2578063f2fde38b1161007c578063f2fde38b1461070b578063f3ae24151461071e578063f7c618c114610731578063fc2aff3a1461075857600080fd5b8063e859c0b5146106dc578063eedc966a146106e5578063f0f44260146106f857600080fd5b8063cf42947b14610658578063d1c1b4a81461066b578063d1c339d01461067e578063d3e33ddd14610691578063d8e6e417146106a4578063e3725b15146106c757600080fd5b80639dd2a9361161013b5780639dd2a93614610543578063a1a6690f14610603578063a5e90eee1461060c578063a64b1d5f1461061f578063c2c518e114610628578063ca45412d1461063057600080fd5b80638da5cb5b146105565780638dbb1e3a1461056c57806393f1a40b1461057f578063957cb949146105d457806395ea0db1146105dd57806398ec8da6146105f057600080fd5b8063440d724811610241578063630b5ba1116101fa57806378e97925116101d457806378e97925146105015780637b0472f0146105285780638456cb591461053b57806387642b7a1461054357600080fd5b8063630b5ba1146104de5780636a760b80146104e6578063715018a6146104f957600080fd5b8063440d72481461044c578063441a3e701461046f57806351eb05a6146104825780635312ea8e146104955780635c975abb146104a857806361d027b3146104b357600080fd5b806331326d161161029357806331326d16146103ce5780633197cbb6146103d75780633b57e4af146103fc5780633c6a4e611461040f5780633e4a56fb146104225780633f4ba83a1461044457600080fd5b8063081e3eda146102db578063103b7397146102f25780631514617e146103305780631526fe27146103575780631653fd33146103a657806330eb1278146103b9575b600080fd5b6006545b6040519081526020015b60405180910390f35b600080516020612e9783398151915260005260016020527f3c2285c553468ca8f30447b24bb463c127f1b840e23a0cafa23caa79d906669a546102df565b6102df7f000000000000000000000000000000000000000000000000000000000000000081565b61036a610365366004612a13565b610770565b604080516001600160a01b03909616865260208601949094529284019190915263ffffffff16606083015261ffff16608082015260a0016102e9565b6102df6103b4366004612a43565b6107c8565b6103cc6103c7366004612a6f565b61090c565b005b6102df600d5481565b600b546103e79063ffffffff1681565b60405163ffffffff90911681526020016102e9565b6103cc61040a366004612a13565b610997565b6103cc61041d366004612a13565b610b66565b610435610430366004612a43565b610cfc565b6040516102e993929190612a99565b6103cc610ebe565b61045f61045a366004612af9565b610ef6565b60405190151581526020016102e9565b6103cc61047d366004612b1b565b610f61565b6103cc610490366004612a13565b6110c0565b6103cc6104a3366004612a13565b6110d4565b60005460ff1661045f565b6003546104c6906001600160a01b031681565b6040516001600160a01b0390911681526020016102e9565b6103cc61118c565b6103cc6104f4366004612a13565b61119c565b6103cc6113b8565b6103e77f000000000000000000000000000000000000000000000000000000000000000081565b6103cc610536366004612b1b565b6113ca565b6103cc6114cf565b6103cc610551366004612a13565b611505565b60005461010090046001600160a01b03166104c6565b6102df61057a366004612b1b565b611545565b6105b961058d366004612a43565b600860209081526000928352604080842090915290825290208054600182015460029092015490919083565b604080519384526020840192909252908201526060016102e9565b6102df600c5481565b6103cc6105eb366004612af9565b611628565b6103cc6105fe366004612b5d565b61169d565b6102df600a5481565b6103cc61061a366004612ba4565b611954565b6102df60055481565b6103cc6119b1565b61064361063e366004612bdb565b611a1e565b604080519283526020830191909152016102e9565b6103cc610666366004612c10565b611a68565b6103cc610679366004612c36565b611aca565b6004546104c6906001600160a01b031681565b6103cc61069f366004612c5b565b611b97565b61045f6106b2366004612af9565b60076020526000908152604090205460ff1681565b6106cf611c23565b6040516102e99190612c87565b6102df600e5481565b6102df6106f3366004612af9565b611c3c565b6103cc610706366004612af9565b611cd7565b6103cc610719366004612af9565b611d4c565b61045f61072c366004612af9565b611dc2565b6104c67f000000000000000000000000000000000000000000000000000000000000000081565b6103cc610766366004612cd4565b611e02565b905090565b6006818154811061078057600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b039092169350919063ffffffff811690640100000000900461ffff1685565b600080600684815481106107de576107de612cf9565b600091825260208083208784526008825260408085206001600160a01b03891686529092529220600260049092029092019081015460038201549193509063ffffffff16421180156108335750600183015415155b156108c35760038301546000906108509063ffffffff1642611545565b90506000600a548560030160049054906101000a900461ffff1661ffff166005548461087c9190612d25565b6108869190612d25565b6108909190612d3c565b60018601549091506108aa670de0b6b3a764000083612d25565b6108b49190612d3c565b6108be9084612d5e565b925050505b600282015460018301548354670de0b6b3a7640000906108e4908590612d25565b6108ee9190612d3c565b6108f89190612d71565b6109029190612d5e565b9695505050505050565b61091533611dc2565b61093257604051637c3ea23f60e01b815260040160405180910390fd5b61093b82610ef6565b1561095957604051634477699960e11b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0383160161098c576109883382611e3c565b5050565b610988823383611ecf565b6109a081611fc1565b60006109ac8233610cfc565b50509050600080821115610aca576000838152600960209081526040808320338452909152812054905b81811015610ac75760008581526009602090815260408083203384529091528120805483908110610a0957610a09612cf9565b6000918252602080832060029092029091015488835260098252604080842033855290925291208054919250429184908110610a4757610a47612cf9565b9060005260206000209060020201600101541115610a655750610ac7565b610a6f8185612d5e565b6000878152600960209081526040808320338452909152902080549195509083908110610a9e57610a9e612cf9565b600091825260208220600290910201818155600101555080610abf81612d84565b9150506109d6565b50505b8015610adf57610ada33826120d2565b610b2c565b60405162461bcd60e51b815260206004820181905260248201527f546f6b656e7320617265206e6f7420617661696c61626c6520666f72206e6f7760448201526064015b60405180910390fd5b60405181815233907f7391907e2ab707a2bed13f0fa64fdaa84d5fb991113e1dad366f47b55ec6e6119060200160405180910390a2505050565b610b6f81611fc1565b6000610b7b8233610cfc565b5091505060008111610bdb5760405162461bcd60e51b8152602060048201526024808201527f546f74616c2076657374696e6720746f6b656e732063616e206e6f74206265206044820152637a65726f60e01b6064820152608401610b23565b60006103e8600c5483610bee9190612d25565b610bf89190612d3c565b905060006103e8600d5484610c0d9190612d25565b610c179190612d3c565b905060006103e8600e5485610c2c9190612d25565b610c369190612d3c565b9050610c4233846120d2565b600354610c7c906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169116846121ef565b600454610cb6906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169116836121ef565b610cc08533612252565b60405183815233907f1be3144880c716b1152eab5fbba4f339f9590430ecfd4f1c7cd4a10e3c2797a59060200160405180910390a25050505050565b60008281526009602090815260408083206001600160a01b03851684529091528120819060609082805b8254811015610eb45742838281548110610d4257610d42612cf9565b9060005260206000209060020201600101541115610e705781600003610dd0578254610d6f908290612d71565b67ffffffffffffffff811115610d8757610d87612d9d565b604051908082528060200260200182016040528015610dcc57816020015b6040805180820190915260008082526020820152815260200190600190039081610da55790505b5093505b828181548110610de257610de2612cf9565b906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050848381518110610e2157610e21612cf9565b60200260200101819052508180610e3790612d84565b925050828181548110610e4c57610e4c612cf9565b90600052602060002090600202016000015485610e699190612d5e565b9450610ea2565b828181548110610e8257610e82612cf9565b90600052602060002090600202016000015486610e9f9190612d5e565b95505b80610eac81612d84565b915050610d26565b5050509250925092565b610ec733611dc2565b610ee457604051637c3ea23f60e01b815260040160405180910390fd5b610eec6122eb565b610ef4612334565b565b600654600090815b81811015610f575760068181548110610f1957610f19612cf9565b60009182526020909120600490910201546001600160a01b0390811690851603610f47575060019392505050565b610f5081612d84565b9050610efe565b5060009392505050565b610f69612386565b600060068381548110610f7e57610f7e612cf9565b600091825260208083208684526008825260408085203386529092529220805460049092029092019250831115610ff75760405162461bcd60e51b815260206004820152601c60248201527f43616e206e6f74207769746864726177207468697320616d6f756e74000000006044820152606401610b23565b61100084611fc1565b61100a84336107c8565b6002820155805483908290600090611023908490612d71565b925050819055508282600101600082825461103e9190612d71565b909155505060028201548154670de0b6b3a76400009161105d91612d25565b6110679190612d3c565b60018201558154611082906001600160a01b031633856121ef565b604051838152849033907ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568906020015b60405180910390a350505050565b6110c8612386565b6110d181611fc1565b50565b6000600682815481106110e9576110e9612cf9565b600091825260208083208584526008825260408085203386529092529083208054600493909302909101600181018054919550919383929161112c908490612d71565b909155505060008083556001830181905560028301558254611158906001600160a01b031633836121ef565b604051818152849033907fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595906020016110b2565b611194612386565b610ef46123cc565b6111a4612386565b6000600682815481106111b9576111b9612cf9565b600091825260208083208584526008825260408085203386529092529220600490910290910191506111ea83611fc1565b60006111f684336107c8565b9050600081116112575760405162461bcd60e51b815260206004820152602660248201527f416d6f756e74206f6620746f6b656e732063616e206e6f74206265207a65726f6044820152652076616c756560d01b6064820152608401610b23565b60006112837f000000000000000000000000000000000000000000000000000000000000000042612d5e565b60008681526009602090815260408083203384529091529020805491925090606410156113115760405162461bcd60e51b815260206004820152603660248201527f557365722063616e206e6f74206578656375746520766573742066756e6374696044820152756f6e206d6f7265207468616e203130302074696d657360501b6064820152608401610b23565b60408051808201909152838152602080820184815283546001818101865560008681529384209451600292830290950194855591519390910192909255858201558501548454670de0b6b3a76400009161136a91612d25565b6113749190612d3c565b6001850155604051838152869033907ffbeff59d2bfda0d79ea8a29f8c57c66d48c7a13eabbdb90908d9115ec41c9dc69060200160405180910390a3505050505050565b6113c06123f3565b610ef46000612453565b6113d2612386565b6000600683815481106113e7576113e7612cf9565b6000918252602080832086845260088252604080852033865290925292206004909102909101915061141884611fc1565b815461142f906001600160a01b03163330866124ac565b61143984336107c8565b6002820155805483908290600090611452908490612d5e565b925050819055508282600101600082825461146d9190612d5e565b909155505060028201548154670de0b6b3a76400009161148c91612d25565b6114969190612d3c565b6001820155604051838152849033907f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee90906020016110b2565b6114d833611dc2565b6114f557604051637c3ea23f60e01b815260040160405180910390fd5b6114fd612386565b610ef46124e4565b60405162461bcd60e51b81526020600482015260156024820152742ab739bab83837b93a32b21037b832b930ba34b7b760591b6044820152606401610b23565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff1683116115a0577f000000000000000000000000000000000000000000000000000000000000000063ffffffff166115a2565b825b600b5490935063ffffffff168311806115e057507f000000000000000000000000000000000000000000000000000000000000000063ffffffff1682105b156115ed57506000611622565b600b5463ffffffff1682111561161857600b5461161190849063ffffffff16612d71565b9050611622565b6116118383612d71565b92915050565b6116306123f3565b6001600160a01b03811661167b5760405162461bcd60e51b81526020600482015260126024820152712d32b9379030b2323932b9b99032b93937b960711b6044820152606401610b23565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6116a633611dc2565b6116c357604051637c3ea23f60e01b815260040160405180910390fd5b6001600160a01b03821660009081526007602052604090205460ff161561172c5760405162461bcd60e51b815260206004820152601d60248201527f5374616b696e6720746f6b656e2077617320616c7265616479207365740000006044820152606401610b23565b6006546005116117885760405162461bcd60e51b815260206004820152602160248201527f4e6f206d6f7265207468656e203520706f6f6c732063616e20626520616464656044820152601960fa1b6064820152608401610b23565b8015611796576117966123cc565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff1642116117f1577f000000000000000000000000000000000000000000000000000000000000000063ffffffff166117f3565b425b90508361ffff16600a600082825461180b9190612d5e565b90915550506040805160a0810182526001600160a01b039485168082526000602080840182815284860183815263ffffffff9788166060870190815261ffff9b8c1660808801908152600680546001808201835591885298517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f6004909a02998a0180546001600160a01b03191691909e1617909c5592517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d4088015590517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d41870155517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d42909501805491519590971665ffffffffffff19909116176401000000009490991693909302979097179093559185526007909152909220805460ff1916909117905550565b61195c6123f3565b611975600080516020612e978339815191528383612521565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b6119ba33611dc2565b6119d757604051637c3ea23f60e01b815260040160405180910390fd5b6119f1600080516020612e97833981519152336000612521565b60405133907f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc590600090a2565b60096020528260005260406000206020528160005260406000208181548110611a4657600080fd5b6000918252602090912060029091020180546001909101549093509150839050565b611a7133611dc2565b611a8e57604051637c3ea23f60e01b815260040160405180910390fd5b600b8054829190600090611aa990849063ffffffff16612db3565b92506101000a81548163ffffffff021916908363ffffffff16021790555050565b611ad333611dc2565b611af057604051637c3ea23f60e01b815260040160405180910390fd5b8015611afe57611afe6123cc565b8161ffff1660068481548110611b1657611b16612cf9565b6000918252602090912060049091020160030154600a54611b4391640100000000900461ffff1690612d71565b611b4d9190612d5e565b600a819055508160068481548110611b6757611b67612cf9565b906000526020600020906004020160030160046101000a81548161ffff021916908361ffff160217905550505050565b611b9f6123f3565b80611baa8385612d5e565b611bb49190612d5e565b6103e814611c155760405162461bcd60e51b815260206004820152602860248201527f546f74616c2070657263656e746167652073686f756c642062652031303025206044820152671a5b881d1bdd185b60c21b6064820152608401610b23565b600c92909255600d55600e55565b606061076b600080516020612e97833981519152612548565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601611c6a575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611cae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116229190612dd7565b919050565b611cdf6123f3565b6001600160a01b038116611d2a5760405162461bcd60e51b81526020600482015260126024820152712d32b9379030b2323932b9b99032b93937b960711b6044820152606401610b23565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b611d546123f3565b6001600160a01b038116611db95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b23565b6110d181612453565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff16611622565b611e0b33611dc2565b611e2857604051637c3ea23f60e01b815260040160405180910390fd5b8015611e3657611e366123cc565b50600555565b604080516000808252602082019092526001600160a01b038416908390604051611e669190612e14565b60006040518083038185875af1925050503d8060008114611ea3576040519150601f19603f3d011682016040523d82523d6000602084013e611ea8565b606091505b5050905080611eca57604051632e05b05360e21b815260040160405180910390fd5b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611f2b9190612e14565b6000604051808303816000865af19150503d8060008114611f68576040519150601f19603f3d011682016040523d82523d6000602084013e611f6d565b606091505b50915091506000828015611f99575081511580611f99575081806020019051810190611f999190612e30565b905080611fb957604051632fdb1b7f60e11b815260040160405180910390fd5b505050505050565b600060068281548110611fd657611fd6612cf9565b60009182526020909120600490910201600381015490915063ffffffff164211611ffe575050565b806001015460000361202357600301805463ffffffff19164263ffffffff1617905550565b600381015460009061203b9063ffffffff1642611545565b90506000600a548360030160049054906101000a900461ffff1661ffff16600554846120679190612d25565b6120719190612d25565b61207b9190612d3c565b6001840154909150612095670de0b6b3a764000083612d25565b61209f9190612d3c565b8360020160008282546120b29190612d5e565b90915550505050600301805463ffffffff19164263ffffffff1617905550565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215d9190612dd7565b9050808211156121bf5760405162461bcd60e51b815260206004820152602760248201527f4e6f7420656e6f75676820746f6b656e73206f6e2074686520736d61727420636044820152661bdb9d1c9858dd60ca1b6064820152608401610b23565b611eca6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001684845b6040516001600160a01b038316602482015260448101829052611eca90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526125b4565b60008281526009602090815260408083206001600160a01b03851684529091528120905b81548110156122e5574282828154811061229257612292612cf9565b90600052602060002090600202016001015411156122d3578181815481106122bc576122bc612cf9565b600091825260208220600290910201818155600101555b806122dd81612d84565b915050612276565b50505050565b60005460ff16610ef45760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610b23565b61233c6122eb565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60005460ff1615610ef45760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610b23565b60065460005b81811015610988576123e381611fc1565b6123ec81612d84565b90506123d2565b6000546001600160a01b03610100909104163314610ef45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b23565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b6040516001600160a01b03808516602483015283166044820152606481018290526122e59085906323b872dd60e01b9060840161221b565b6124ec612386565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586123693390565b600083815260016020908152604080832060029092529091206122e5919084846064612686565b6000818152600160209081526040918290208054835181840281018401909452808452606093928301828280156125a857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161258a575b50505050509050919050565b6000612609826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166126a99092919063ffffffff16565b805190915015611eca57808060200190518101906126279190612e30565b611eca5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610b23565b60008261269d576126988686866126c0565b610902565b610902868686856127e8565b60606126b8848460008561289a565b949350505050565b6001600160a01b0381166000908152602083905260409020805460ff169081156127e057600180820154865490916000916126fb9190612d71565b905080821461278857600087828154811061271857612718612cf9565b9060005260206000200160009054906101000a90046001600160a01b031690508088848154811061274b5761274b612cf9565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b8680548061279857612798612e4d565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff161580156126b8578454821161282c5760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b03881660008181528a83529586209451855460ff1916901515178555915193830193909355885491820189558884529190922090910180546001600160a01b0319169091179055949350505050565b6060824710156128fb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610b23565b600080866001600160a01b031685876040516129179190612e14565b60006040518083038185875af1925050503d8060008114612954576040519150601f19603f3d011682016040523d82523d6000602084013e612959565b606091505b509150915061296a87838387612975565b979650505050505050565b606083156129e45782516000036129dd576001600160a01b0385163b6129dd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b23565b50816126b8565b6126b883838151156129f95781518083602001fd5b8060405162461bcd60e51b8152600401610b239190612e63565b600060208284031215612a2557600080fd5b5035919050565b80356001600160a01b0381168114611cd257600080fd5b60008060408385031215612a5657600080fd5b82359150612a6660208401612a2c565b90509250929050565b60008060408385031215612a8257600080fd5b612a8b83612a2c565b946020939093013593505050565b600060608201858352602085818501526040606081860152828651808552608087019150838801945060005b81811015612aea57855180518452850151858401529484019491830191600101612ac5565b50909998505050505050505050565b600060208284031215612b0b57600080fd5b612b1482612a2c565b9392505050565b60008060408385031215612b2e57600080fd5b50508035926020909101359150565b803561ffff81168114611cd257600080fd5b80151581146110d157600080fd5b600080600060608486031215612b7257600080fd5b612b7b84612b3d565b9250612b8960208501612a2c565b91506040840135612b9981612b4f565b809150509250925092565b60008060408385031215612bb757600080fd5b612bc083612a2c565b91506020830135612bd081612b4f565b809150509250929050565b600080600060608486031215612bf057600080fd5b83359250612c0060208501612a2c565b9150604084013590509250925092565b600060208284031215612c2257600080fd5b813563ffffffff81168114612b1457600080fd5b600080600060608486031215612c4b57600080fd5b83359250612b8960208501612b3d565b600080600060608486031215612c7057600080fd5b505081359360208301359350604090920135919050565b6020808252825182820181905260009190848201906040850190845b81811015612cc85783516001600160a01b031683529284019291840191600101612ca3565b50909695505050505050565b60008060408385031215612ce757600080fd5b823591506020830135612bd081612b4f565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761162257611622612d0f565b600082612d5957634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561162257611622612d0f565b8181038181111561162257611622612d0f565b600060018201612d9657612d96612d0f565b5060010190565b634e487b7160e01b600052604160045260246000fd5b63ffffffff818116838216019080821115612dd057612dd0612d0f565b5092915050565b600060208284031215612de957600080fd5b5051919050565b60005b83811015612e0b578181015183820152602001612df3565b50506000910152565b60008251612e26818460208701612df0565b9190910192915050565b600060208284031215612e4257600080fd5b8151612b1481612b4f565b634e487b7160e01b600052603160045260246000fd5b6020815260008251806020840152612e82816040850160208701612df0565b601f01601f1916919091016040019291505056fe6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6fa2646970667358221220ab8e3f2752778a65ebbe5dd1124ebf018dcab6a6d98e5b26c0d85dcf05e8564564736f6c634300081300330000000000000000000000002b1d36f5b61addaf7da7ebbd11b35fd8cfb0de31000000000000000000000000000000000000000000000000003211b70ff5ff000000000000000000000000000000000000000000000000000000000064e74483000000000000000000000000000000000000000000000000000000000076a700
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102d65760003560e01c80638da5cb5b11610182578063cf42947b116100e9578063e859c0b5116100a2578063f2fde38b1161007c578063f2fde38b1461070b578063f3ae24151461071e578063f7c618c114610731578063fc2aff3a1461075857600080fd5b8063e859c0b5146106dc578063eedc966a146106e5578063f0f44260146106f857600080fd5b8063cf42947b14610658578063d1c1b4a81461066b578063d1c339d01461067e578063d3e33ddd14610691578063d8e6e417146106a4578063e3725b15146106c757600080fd5b80639dd2a9361161013b5780639dd2a93614610543578063a1a6690f14610603578063a5e90eee1461060c578063a64b1d5f1461061f578063c2c518e114610628578063ca45412d1461063057600080fd5b80638da5cb5b146105565780638dbb1e3a1461056c57806393f1a40b1461057f578063957cb949146105d457806395ea0db1146105dd57806398ec8da6146105f057600080fd5b8063440d724811610241578063630b5ba1116101fa57806378e97925116101d457806378e97925146105015780637b0472f0146105285780638456cb591461053b57806387642b7a1461054357600080fd5b8063630b5ba1146104de5780636a760b80146104e6578063715018a6146104f957600080fd5b8063440d72481461044c578063441a3e701461046f57806351eb05a6146104825780635312ea8e146104955780635c975abb146104a857806361d027b3146104b357600080fd5b806331326d161161029357806331326d16146103ce5780633197cbb6146103d75780633b57e4af146103fc5780633c6a4e611461040f5780633e4a56fb146104225780633f4ba83a1461044457600080fd5b8063081e3eda146102db578063103b7397146102f25780631514617e146103305780631526fe27146103575780631653fd33146103a657806330eb1278146103b9575b600080fd5b6006545b6040519081526020015b60405180910390f35b600080516020612e9783398151915260005260016020527f3c2285c553468ca8f30447b24bb463c127f1b840e23a0cafa23caa79d906669a546102df565b6102df7f000000000000000000000000000000000000000000000000000000000076a70081565b61036a610365366004612a13565b610770565b604080516001600160a01b03909616865260208601949094529284019190915263ffffffff16606083015261ffff16608082015260a0016102e9565b6102df6103b4366004612a43565b6107c8565b6103cc6103c7366004612a6f565b61090c565b005b6102df600d5481565b600b546103e79063ffffffff1681565b60405163ffffffff90911681526020016102e9565b6103cc61040a366004612a13565b610997565b6103cc61041d366004612a13565b610b66565b610435610430366004612a43565b610cfc565b6040516102e993929190612a99565b6103cc610ebe565b61045f61045a366004612af9565b610ef6565b60405190151581526020016102e9565b6103cc61047d366004612b1b565b610f61565b6103cc610490366004612a13565b6110c0565b6103cc6104a3366004612a13565b6110d4565b60005460ff1661045f565b6003546104c6906001600160a01b031681565b6040516001600160a01b0390911681526020016102e9565b6103cc61118c565b6103cc6104f4366004612a13565b61119c565b6103cc6113b8565b6103e77f0000000000000000000000000000000000000000000000000000000064e7448381565b6103cc610536366004612b1b565b6113ca565b6103cc6114cf565b6103cc610551366004612a13565b611505565b60005461010090046001600160a01b03166104c6565b6102df61057a366004612b1b565b611545565b6105b961058d366004612a43565b600860209081526000928352604080842090915290825290208054600182015460029092015490919083565b604080519384526020840192909252908201526060016102e9565b6102df600c5481565b6103cc6105eb366004612af9565b611628565b6103cc6105fe366004612b5d565b61169d565b6102df600a5481565b6103cc61061a366004612ba4565b611954565b6102df60055481565b6103cc6119b1565b61064361063e366004612bdb565b611a1e565b604080519283526020830191909152016102e9565b6103cc610666366004612c10565b611a68565b6103cc610679366004612c36565b611aca565b6004546104c6906001600160a01b031681565b6103cc61069f366004612c5b565b611b97565b61045f6106b2366004612af9565b60076020526000908152604090205460ff1681565b6106cf611c23565b6040516102e99190612c87565b6102df600e5481565b6102df6106f3366004612af9565b611c3c565b6103cc610706366004612af9565b611cd7565b6103cc610719366004612af9565b611d4c565b61045f61072c366004612af9565b611dc2565b6104c67f0000000000000000000000002b1d36f5b61addaf7da7ebbd11b35fd8cfb0de3181565b6103cc610766366004612cd4565b611e02565b905090565b6006818154811061078057600080fd5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b039092169350919063ffffffff811690640100000000900461ffff1685565b600080600684815481106107de576107de612cf9565b600091825260208083208784526008825260408085206001600160a01b03891686529092529220600260049092029092019081015460038201549193509063ffffffff16421180156108335750600183015415155b156108c35760038301546000906108509063ffffffff1642611545565b90506000600a548560030160049054906101000a900461ffff1661ffff166005548461087c9190612d25565b6108869190612d25565b6108909190612d3c565b60018601549091506108aa670de0b6b3a764000083612d25565b6108b49190612d3c565b6108be9084612d5e565b925050505b600282015460018301548354670de0b6b3a7640000906108e4908590612d25565b6108ee9190612d3c565b6108f89190612d71565b6109029190612d5e565b9695505050505050565b61091533611dc2565b61093257604051637c3ea23f60e01b815260040160405180910390fd5b61093b82610ef6565b1561095957604051634477699960e11b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0383160161098c576109883382611e3c565b5050565b610988823383611ecf565b6109a081611fc1565b60006109ac8233610cfc565b50509050600080821115610aca576000838152600960209081526040808320338452909152812054905b81811015610ac75760008581526009602090815260408083203384529091528120805483908110610a0957610a09612cf9565b6000918252602080832060029092029091015488835260098252604080842033855290925291208054919250429184908110610a4757610a47612cf9565b9060005260206000209060020201600101541115610a655750610ac7565b610a6f8185612d5e565b6000878152600960209081526040808320338452909152902080549195509083908110610a9e57610a9e612cf9565b600091825260208220600290910201818155600101555080610abf81612d84565b9150506109d6565b50505b8015610adf57610ada33826120d2565b610b2c565b60405162461bcd60e51b815260206004820181905260248201527f546f6b656e7320617265206e6f7420617661696c61626c6520666f72206e6f7760448201526064015b60405180910390fd5b60405181815233907f7391907e2ab707a2bed13f0fa64fdaa84d5fb991113e1dad366f47b55ec6e6119060200160405180910390a2505050565b610b6f81611fc1565b6000610b7b8233610cfc565b5091505060008111610bdb5760405162461bcd60e51b8152602060048201526024808201527f546f74616c2076657374696e6720746f6b656e732063616e206e6f74206265206044820152637a65726f60e01b6064820152608401610b23565b60006103e8600c5483610bee9190612d25565b610bf89190612d3c565b905060006103e8600d5484610c0d9190612d25565b610c179190612d3c565b905060006103e8600e5485610c2c9190612d25565b610c369190612d3c565b9050610c4233846120d2565b600354610c7c906001600160a01b037f0000000000000000000000002b1d36f5b61addaf7da7ebbd11b35fd8cfb0de3181169116846121ef565b600454610cb6906001600160a01b037f0000000000000000000000002b1d36f5b61addaf7da7ebbd11b35fd8cfb0de3181169116836121ef565b610cc08533612252565b60405183815233907f1be3144880c716b1152eab5fbba4f339f9590430ecfd4f1c7cd4a10e3c2797a59060200160405180910390a25050505050565b60008281526009602090815260408083206001600160a01b03851684529091528120819060609082805b8254811015610eb45742838281548110610d4257610d42612cf9565b9060005260206000209060020201600101541115610e705781600003610dd0578254610d6f908290612d71565b67ffffffffffffffff811115610d8757610d87612d9d565b604051908082528060200260200182016040528015610dcc57816020015b6040805180820190915260008082526020820152815260200190600190039081610da55790505b5093505b828181548110610de257610de2612cf9565b906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050848381518110610e2157610e21612cf9565b60200260200101819052508180610e3790612d84565b925050828181548110610e4c57610e4c612cf9565b90600052602060002090600202016000015485610e699190612d5e565b9450610ea2565b828181548110610e8257610e82612cf9565b90600052602060002090600202016000015486610e9f9190612d5e565b95505b80610eac81612d84565b915050610d26565b5050509250925092565b610ec733611dc2565b610ee457604051637c3ea23f60e01b815260040160405180910390fd5b610eec6122eb565b610ef4612334565b565b600654600090815b81811015610f575760068181548110610f1957610f19612cf9565b60009182526020909120600490910201546001600160a01b0390811690851603610f47575060019392505050565b610f5081612d84565b9050610efe565b5060009392505050565b610f69612386565b600060068381548110610f7e57610f7e612cf9565b600091825260208083208684526008825260408085203386529092529220805460049092029092019250831115610ff75760405162461bcd60e51b815260206004820152601c60248201527f43616e206e6f74207769746864726177207468697320616d6f756e74000000006044820152606401610b23565b61100084611fc1565b61100a84336107c8565b6002820155805483908290600090611023908490612d71565b925050819055508282600101600082825461103e9190612d71565b909155505060028201548154670de0b6b3a76400009161105d91612d25565b6110679190612d3c565b60018201558154611082906001600160a01b031633856121ef565b604051838152849033907ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568906020015b60405180910390a350505050565b6110c8612386565b6110d181611fc1565b50565b6000600682815481106110e9576110e9612cf9565b600091825260208083208584526008825260408085203386529092529083208054600493909302909101600181018054919550919383929161112c908490612d71565b909155505060008083556001830181905560028301558254611158906001600160a01b031633836121ef565b604051818152849033907fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595906020016110b2565b611194612386565b610ef46123cc565b6111a4612386565b6000600682815481106111b9576111b9612cf9565b600091825260208083208584526008825260408085203386529092529220600490910290910191506111ea83611fc1565b60006111f684336107c8565b9050600081116112575760405162461bcd60e51b815260206004820152602660248201527f416d6f756e74206f6620746f6b656e732063616e206e6f74206265207a65726f6044820152652076616c756560d01b6064820152608401610b23565b60006112837f000000000000000000000000000000000000000000000000000000000076a70042612d5e565b60008681526009602090815260408083203384529091529020805491925090606410156113115760405162461bcd60e51b815260206004820152603660248201527f557365722063616e206e6f74206578656375746520766573742066756e6374696044820152756f6e206d6f7265207468616e203130302074696d657360501b6064820152608401610b23565b60408051808201909152838152602080820184815283546001818101865560008681529384209451600292830290950194855591519390910192909255858201558501548454670de0b6b3a76400009161136a91612d25565b6113749190612d3c565b6001850155604051838152869033907ffbeff59d2bfda0d79ea8a29f8c57c66d48c7a13eabbdb90908d9115ec41c9dc69060200160405180910390a3505050505050565b6113c06123f3565b610ef46000612453565b6113d2612386565b6000600683815481106113e7576113e7612cf9565b6000918252602080832086845260088252604080852033865290925292206004909102909101915061141884611fc1565b815461142f906001600160a01b03163330866124ac565b61143984336107c8565b6002820155805483908290600090611452908490612d5e565b925050819055508282600101600082825461146d9190612d5e565b909155505060028201548154670de0b6b3a76400009161148c91612d25565b6114969190612d3c565b6001820155604051838152849033907f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee90906020016110b2565b6114d833611dc2565b6114f557604051637c3ea23f60e01b815260040160405180910390fd5b6114fd612386565b610ef46124e4565b60405162461bcd60e51b81526020600482015260156024820152742ab739bab83837b93a32b21037b832b930ba34b7b760591b6044820152606401610b23565b60007f0000000000000000000000000000000000000000000000000000000064e7448363ffffffff1683116115a0577f0000000000000000000000000000000000000000000000000000000064e7448363ffffffff166115a2565b825b600b5490935063ffffffff168311806115e057507f0000000000000000000000000000000000000000000000000000000064e7448363ffffffff1682105b156115ed57506000611622565b600b5463ffffffff1682111561161857600b5461161190849063ffffffff16612d71565b9050611622565b6116118383612d71565b92915050565b6116306123f3565b6001600160a01b03811661167b5760405162461bcd60e51b81526020600482015260126024820152712d32b9379030b2323932b9b99032b93937b960711b6044820152606401610b23565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6116a633611dc2565b6116c357604051637c3ea23f60e01b815260040160405180910390fd5b6001600160a01b03821660009081526007602052604090205460ff161561172c5760405162461bcd60e51b815260206004820152601d60248201527f5374616b696e6720746f6b656e2077617320616c7265616479207365740000006044820152606401610b23565b6006546005116117885760405162461bcd60e51b815260206004820152602160248201527f4e6f206d6f7265207468656e203520706f6f6c732063616e20626520616464656044820152601960fa1b6064820152608401610b23565b8015611796576117966123cc565b60007f0000000000000000000000000000000000000000000000000000000064e7448363ffffffff1642116117f1577f0000000000000000000000000000000000000000000000000000000064e7448363ffffffff166117f3565b425b90508361ffff16600a600082825461180b9190612d5e565b90915550506040805160a0810182526001600160a01b039485168082526000602080840182815284860183815263ffffffff9788166060870190815261ffff9b8c1660808801908152600680546001808201835591885298517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f6004909a02998a0180546001600160a01b03191691909e1617909c5592517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d4088015590517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d41870155517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d42909501805491519590971665ffffffffffff19909116176401000000009490991693909302979097179093559185526007909152909220805460ff1916909117905550565b61195c6123f3565b611975600080516020612e978339815191528383612521565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b6119ba33611dc2565b6119d757604051637c3ea23f60e01b815260040160405180910390fd5b6119f1600080516020612e97833981519152336000612521565b60405133907f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc590600090a2565b60096020528260005260406000206020528160005260406000208181548110611a4657600080fd5b6000918252602090912060029091020180546001909101549093509150839050565b611a7133611dc2565b611a8e57604051637c3ea23f60e01b815260040160405180910390fd5b600b8054829190600090611aa990849063ffffffff16612db3565b92506101000a81548163ffffffff021916908363ffffffff16021790555050565b611ad333611dc2565b611af057604051637c3ea23f60e01b815260040160405180910390fd5b8015611afe57611afe6123cc565b8161ffff1660068481548110611b1657611b16612cf9565b6000918252602090912060049091020160030154600a54611b4391640100000000900461ffff1690612d71565b611b4d9190612d5e565b600a819055508160068481548110611b6757611b67612cf9565b906000526020600020906004020160030160046101000a81548161ffff021916908361ffff160217905550505050565b611b9f6123f3565b80611baa8385612d5e565b611bb49190612d5e565b6103e814611c155760405162461bcd60e51b815260206004820152602860248201527f546f74616c2070657263656e746167652073686f756c642062652031303025206044820152671a5b881d1bdd185b60c21b6064820152608401610b23565b600c92909255600d55600e55565b606061076b600080516020612e97833981519152612548565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601611c6a575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611cae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116229190612dd7565b919050565b611cdf6123f3565b6001600160a01b038116611d2a5760405162461bcd60e51b81526020600482015260126024820152712d32b9379030b2323932b9b99032b93937b960711b6044820152606401610b23565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b611d546123f3565b6001600160a01b038116611db95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b23565b6110d181612453565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff16611622565b611e0b33611dc2565b611e2857604051637c3ea23f60e01b815260040160405180910390fd5b8015611e3657611e366123cc565b50600555565b604080516000808252602082019092526001600160a01b038416908390604051611e669190612e14565b60006040518083038185875af1925050503d8060008114611ea3576040519150601f19603f3d011682016040523d82523d6000602084013e611ea8565b606091505b5050905080611eca57604051632e05b05360e21b815260040160405180910390fd5b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611f2b9190612e14565b6000604051808303816000865af19150503d8060008114611f68576040519150601f19603f3d011682016040523d82523d6000602084013e611f6d565b606091505b50915091506000828015611f99575081511580611f99575081806020019051810190611f999190612e30565b905080611fb957604051632fdb1b7f60e11b815260040160405180910390fd5b505050505050565b600060068281548110611fd657611fd6612cf9565b60009182526020909120600490910201600381015490915063ffffffff164211611ffe575050565b806001015460000361202357600301805463ffffffff19164263ffffffff1617905550565b600381015460009061203b9063ffffffff1642611545565b90506000600a548360030160049054906101000a900461ffff1661ffff16600554846120679190612d25565b6120719190612d25565b61207b9190612d3c565b6001840154909150612095670de0b6b3a764000083612d25565b61209f9190612d3c565b8360020160008282546120b29190612d5e565b90915550505050600301805463ffffffff19164263ffffffff1617905550565b6040516370a0823160e01b81523060048201526000907f0000000000000000000000002b1d36f5b61addaf7da7ebbd11b35fd8cfb0de316001600160a01b0316906370a0823190602401602060405180830381865afa158015612139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215d9190612dd7565b9050808211156121bf5760405162461bcd60e51b815260206004820152602760248201527f4e6f7420656e6f75676820746f6b656e73206f6e2074686520736d61727420636044820152661bdb9d1c9858dd60ca1b6064820152608401610b23565b611eca6001600160a01b037f0000000000000000000000002b1d36f5b61addaf7da7ebbd11b35fd8cfb0de311684845b6040516001600160a01b038316602482015260448101829052611eca90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526125b4565b60008281526009602090815260408083206001600160a01b03851684529091528120905b81548110156122e5574282828154811061229257612292612cf9565b90600052602060002090600202016001015411156122d3578181815481106122bc576122bc612cf9565b600091825260208220600290910201818155600101555b806122dd81612d84565b915050612276565b50505050565b60005460ff16610ef45760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610b23565b61233c6122eb565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60005460ff1615610ef45760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610b23565b60065460005b81811015610988576123e381611fc1565b6123ec81612d84565b90506123d2565b6000546001600160a01b03610100909104163314610ef45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b23565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b6040516001600160a01b03808516602483015283166044820152606481018290526122e59085906323b872dd60e01b9060840161221b565b6124ec612386565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586123693390565b600083815260016020908152604080832060029092529091206122e5919084846064612686565b6000818152600160209081526040918290208054835181840281018401909452808452606093928301828280156125a857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161258a575b50505050509050919050565b6000612609826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166126a99092919063ffffffff16565b805190915015611eca57808060200190518101906126279190612e30565b611eca5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610b23565b60008261269d576126988686866126c0565b610902565b610902868686856127e8565b60606126b8848460008561289a565b949350505050565b6001600160a01b0381166000908152602083905260409020805460ff169081156127e057600180820154865490916000916126fb9190612d71565b905080821461278857600087828154811061271857612718612cf9565b9060005260206000200160009054906101000a90046001600160a01b031690508088848154811061274b5761274b612cf9565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b8680548061279857612798612e4d565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff161580156126b8578454821161282c5760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b03881660008181528a83529586209451855460ff1916901515178555915193830193909355885491820189558884529190922090910180546001600160a01b0319169091179055949350505050565b6060824710156128fb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610b23565b600080866001600160a01b031685876040516129179190612e14565b60006040518083038185875af1925050503d8060008114612954576040519150601f19603f3d011682016040523d82523d6000602084013e612959565b606091505b509150915061296a87838387612975565b979650505050505050565b606083156129e45782516000036129dd576001600160a01b0385163b6129dd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b23565b50816126b8565b6126b883838151156129f95781518083602001fd5b8060405162461bcd60e51b8152600401610b239190612e63565b600060208284031215612a2557600080fd5b5035919050565b80356001600160a01b0381168114611cd257600080fd5b60008060408385031215612a5657600080fd5b82359150612a6660208401612a2c565b90509250929050565b60008060408385031215612a8257600080fd5b612a8b83612a2c565b946020939093013593505050565b600060608201858352602085818501526040606081860152828651808552608087019150838801945060005b81811015612aea57855180518452850151858401529484019491830191600101612ac5565b50909998505050505050505050565b600060208284031215612b0b57600080fd5b612b1482612a2c565b9392505050565b60008060408385031215612b2e57600080fd5b50508035926020909101359150565b803561ffff81168114611cd257600080fd5b80151581146110d157600080fd5b600080600060608486031215612b7257600080fd5b612b7b84612b3d565b9250612b8960208501612a2c565b91506040840135612b9981612b4f565b809150509250925092565b60008060408385031215612bb757600080fd5b612bc083612a2c565b91506020830135612bd081612b4f565b809150509250929050565b600080600060608486031215612bf057600080fd5b83359250612c0060208501612a2c565b9150604084013590509250925092565b600060208284031215612c2257600080fd5b813563ffffffff81168114612b1457600080fd5b600080600060608486031215612c4b57600080fd5b83359250612b8960208501612b3d565b600080600060608486031215612c7057600080fd5b505081359360208301359350604090920135919050565b6020808252825182820181905260009190848201906040850190845b81811015612cc85783516001600160a01b031683529284019291840191600101612ca3565b50909695505050505050565b60008060408385031215612ce757600080fd5b823591506020830135612bd081612b4f565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761162257611622612d0f565b600082612d5957634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561162257611622612d0f565b8181038181111561162257611622612d0f565b600060018201612d9657612d96612d0f565b5060010190565b634e487b7160e01b600052604160045260246000fd5b63ffffffff818116838216019080821115612dd057612dd0612d0f565b5092915050565b600060208284031215612de957600080fd5b5051919050565b60005b83811015612e0b578181015183820152602001612df3565b50506000910152565b60008251612e26818460208701612df0565b9190910192915050565b600060208284031215612e4257600080fd5b8151612b1481612b4f565b634e487b7160e01b600052603160045260246000fd5b6020815260008251806020840152612e82816040850160208701612df0565b601f01601f1916919091016040019291505056fe6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6fa2646970667358221220ab8e3f2752778a65ebbe5dd1124ebf018dcab6a6d98e5b26c0d85dcf05e8564564736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002b1d36f5b61addaf7da7ebbd11b35fd8cfb0de31000000000000000000000000000000000000000000000000003211b70ff5ff000000000000000000000000000000000000000000000000000000000064e74483000000000000000000000000000000000000000000000000000000000076a700
-----Decoded View---------------
Arg [0] : _rewardToken (address): 0x2b1D36f5B61AdDAf7DA7ebbd11B35FD8cfb0DE31
Arg [1] : _rewardTokenPerSecond (uint256): 14093226780000000
Arg [2] : _startTime (uint32): 1692877955
Arg [3] : _vestingDuration (uint256): 7776000
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000002b1d36f5b61addaf7da7ebbd11b35fd8cfb0de31
Arg [1] : 000000000000000000000000000000000000000000000000003211b70ff5ff00
Arg [2] : 0000000000000000000000000000000000000000000000000000000064e74483
Arg [3] : 000000000000000000000000000000000000000000000000000000000076a700
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.004988 | 166,046.4492 | $828.2 |
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.