More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 7,978 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Unstake | 20385059 | 2 days ago | IN | 0 ETH | 0.00065316 | ||||
Unstake | 20344818 | 7 days ago | IN | 0 ETH | 0.000398 | ||||
Unstake | 20344814 | 7 days ago | IN | 0 ETH | 0.00041456 | ||||
Unstake | 20344808 | 7 days ago | IN | 0 ETH | 0.00050586 | ||||
Unstake | 20344558 | 7 days ago | IN | 0 ETH | 0.00051395 | ||||
Unstake | 20343072 | 7 days ago | IN | 0 ETH | 0.00081794 | ||||
Unstake | 20340361 | 8 days ago | IN | 0 ETH | 0.00122459 | ||||
Unstake | 20295127 | 14 days ago | IN | 0 ETH | 0.00014245 | ||||
Unstake | 20295112 | 14 days ago | IN | 0 ETH | 0.00019506 | ||||
Process Rewards | 20259601 | 19 days ago | IN | 0 ETH | 0.00014795 | ||||
Unstake | 20259552 | 19 days ago | IN | 0 ETH | 0.00034835 | ||||
Unstake | 20255038 | 20 days ago | IN | 0 ETH | 0.00058825 | ||||
Unstake | 20255034 | 20 days ago | IN | 0 ETH | 0.00066599 | ||||
Unstake | 20172447 | 31 days ago | IN | 0 ETH | 0.0002848 | ||||
Unstake | 20159663 | 33 days ago | IN | 0 ETH | 0.00025174 | ||||
Unstake | 20159660 | 33 days ago | IN | 0 ETH | 0.00028701 | ||||
Unstake | 20159657 | 33 days ago | IN | 0 ETH | 0.00035531 | ||||
Unstake | 20156009 | 34 days ago | IN | 0 ETH | 0.00046167 | ||||
Unstake | 20148540 | 35 days ago | IN | 0 ETH | 0.00019882 | ||||
Unstake | 20148538 | 35 days ago | IN | 0 ETH | 0.00053588 | ||||
Unstake | 20148518 | 35 days ago | IN | 0 ETH | 0.0005419 | ||||
Unstake | 20148507 | 35 days ago | IN | 0 ETH | 0.00052849 | ||||
Unstake | 20143261 | 35 days ago | IN | 0 ETH | 0.00028633 | ||||
Unstake | 20143258 | 35 days ago | IN | 0 ETH | 0.00037639 | ||||
Unstake | 20116691 | 39 days ago | IN | 0 ETH | 0.00127771 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
HighStreetCorePool
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import "./HighStreetPoolBase.sol"; /** * @title HIGH Core Pool * * @notice Core pools represent permanent pools like HIGH or HIGH/ETH Pair pool, * core pools allow staking for arbitrary periods of time up to 1 year * * @dev See HighStreetPoolBase for more details * */ contract HighStreetCorePool is HighStreetPoolBase { /// @dev Flag indicating pool type, false means "core pool" bool public constant override isFlashPool = false; /// @dev Link to deployed vault instance address public vault; /// @dev Used to calculate vault rewards /// @dev This value is different from "reward per token" used in locked pool /// @dev Note: stakes are different in duration and "weight" reflects that uint256 public vaultRewardsPerWeight; /// @dev Pool tokens value available in the pool; /// pool token examples are HIGH (HIGH core pool) or HIGH/ETH pair (LP core pool) /// @dev For LP core pool this value doesnt' count for HIGH tokens received as Vault rewards /// while for HIGH core pool it does count for such tokens as well uint256 public poolTokenReserve; /** * @dev Fired in receiveVaultRewards() * * @param _by an address that sent the rewards, always a vault * @param amount amount of tokens received */ event VaultRewardsReceived(address indexed _by, uint256 amount); /** * @dev Fired in _processVaultRewards() and dependent functions, like processRewards() * * @param _by an address which executed the function * @param _to an address which received a reward * @param amount amount of reward received */ event VaultRewardsClaimed(address indexed _by, address indexed _to, uint256 amount); /** * @dev Fired in setVault() * * @param _by an address which executed the function, always a factory owner */ event VaultUpdated(address indexed _by, address _fromVal, address _toVal); /** * @dev Creates/deploys an instance of the core pool * * @param _high HIGH ERC20 Token IlluviumERC20 address * @param _factory Pool factory HighStreetPoolFactory instance/address * @param _poolToken token the pool operates on, for example HIGH or HIGH/ETH pair * @param _initBlock initial block used to calculate the rewards * @param _weight number representing a weight of the pool, actual weight fraction * is calculated as that number divided by the total pools weight and doesn't exceed one */ constructor( address _high, HighStreetPoolFactory _factory, address _poolToken, uint256 _initBlock, uint256 _weight ) HighStreetPoolBase(_high, _factory, _poolToken, _initBlock, _weight) {} /** * @notice Calculates current vault rewards value available for address specified * * @dev Performs calculations based on current smart contract state only, * not taking into account any additional time/blocks which might have passed * * @param _staker an address to calculate vault rewards value for * @return pending calculated vault reward value for the given address */ function pendingVaultRewards(address _staker) public view returns (uint256 pending) { User memory user = users[_staker]; return weightToReward(user.totalWeight, vaultRewardsPerWeight) - user.subVaultRewards; } /** * @dev Executed only by the factory owner to Set the vault * * @param _vault an address of deployed IlluviumVault instance */ function setVault(address _vault) external { // verify function is executed by the factory owner require(factory.owner() == msg.sender, "access denied"); // verify input is set require(_vault != address(0), "zero input"); // emit an event emit VaultUpdated(msg.sender, vault, _vault); // update vault address vault = _vault; } /** * @dev Executed by the vault to transfer vault rewards HIGH from the vault * into the pool * * @dev This function is executed only for HIGH core pools * * @param _rewardsAmount amount of HIGH rewards to transfer into the pool */ function receiveVaultRewards(uint256 _rewardsAmount) external { require(msg.sender == vault, "access denied"); // return silently if there is no reward to receive if (_rewardsAmount == 0) { return; } require(usersLockingWeight > 0, "zero locking weight"); transferHighTokenFrom(msg.sender, address(this), _rewardsAmount); vaultRewardsPerWeight += rewardToWeight(_rewardsAmount, usersLockingWeight); // update `poolTokenReserve` only if this is a HIGH Core Pool if (poolToken == HIGH) { poolTokenReserve += _rewardsAmount; } emit VaultRewardsReceived(msg.sender, _rewardsAmount); } /** * @notice Service function to calculate and pay pending vault and yield rewards to the sender * * @dev Internally executes similar function `_processRewards` from the parent smart contract * to calculate and pay yield rewards; adds vault rewards processing * * @dev Can be executed by anyone at any time, but has an effect only when * executed by deposit holder and when at least one block passes from the * previous reward processing * @dev Executed internally when "staking as a pool" (`stakeAsPool`) * @dev When timing conditions are not met (executed too frequently, or after factory * end block), function doesn't throw and exits silently * * @dev Reentrancy safety enforced via `ReentrancyGuard.nonReentrant` * */ function processRewards() external override nonReentrant{ _processRewards(msg.sender, true); User storage user = users[msg.sender]; user.subVaultRewards = weightToReward(user.totalWeight, vaultRewardsPerWeight); } /** * @dev Executed internally by the pool itself (from the parent `HighStreetPoolBase` smart contract) * as part of yield rewards processing logic (`HighStreetPoolBase._processRewards` function) * * @dev Because the reward in all pools should be regarded as a yield staking in HIGH token pool * thus this function can only be excecuted within HIGH token pool * * @param _staker an address which stakes (the yield reward) * @param _amount amount to be staked (yield reward amount) */ function stakeAsPool(address _staker, uint256 _amount) external { require(factory.poolExists(msg.sender), "access denied"); require(poolToken == HIGH, "not HIGH token pool"); _sync(); User storage user = users[_staker]; if (user.tokenAmount > 0) { _processRewards(_staker, false); } uint256 depositWeight = _amount * YEAR_STAKE_WEIGHT_MULTIPLIER; Deposit memory newDeposit = Deposit({ tokenAmount: _amount, lockedFrom: uint64(now256()), lockedUntil: uint64(now256() + 365 days), weight: depositWeight, isYield: true }); user.tokenAmount += _amount; user.rewardAmount += _amount; user.totalWeight += depositWeight; user.deposits.push(newDeposit); usersLockingWeight += depositWeight; user.subYieldRewards = weightToReward(user.totalWeight, yieldRewardsPerWeight); user.subVaultRewards = weightToReward(user.totalWeight, vaultRewardsPerWeight); // update `poolTokenReserve` only if this is a LP Core Pool (stakeAsPool can be executed only for LP pool) poolTokenReserve += _amount; } /** * @inheritdoc HighStreetPoolBase * * @dev Additionally to the parent smart contract, updates vault rewards of the holder, * and updates (increases) pool token reserve (pool tokens value available in the pool) */ function _stake( address _staker, uint256 _amount, uint64 _lockedUntil ) internal override { super._stake(_staker, _amount, _lockedUntil); User storage user = users[_staker]; user.subVaultRewards = weightToReward(user.totalWeight, vaultRewardsPerWeight); poolTokenReserve += _amount; } /** * @inheritdoc HighStreetPoolBase * * @dev Additionally to the parent smart contract, updates vault rewards of the holder, * and updates (decreases) pool token reserve (pool tokens value available in the pool) */ function _unstake( address _staker, uint256 _depositId, uint256 _amount ) internal override { User storage user = users[_staker]; Deposit memory stakeDeposit = user.deposits[_depositId]; require(stakeDeposit.lockedFrom == 0 || now256() > stakeDeposit.lockedUntil, "deposit not yet unlocked"); poolTokenReserve -= _amount; super._unstake(_staker, _depositId, _amount); user.subVaultRewards = weightToReward(user.totalWeight, vaultRewardsPerWeight); } /** * @inheritdoc HighStreetPoolBase * * @dev Additionally to the parent smart contract, updates vault rewards of the holder, * and updates (decreases) pool token reserve (pool tokens value available in the pool) */ function _emergencyWithdraw( address _staker ) internal override { User storage user = users[_staker]; uint256 amount = user.tokenAmount; poolTokenReserve -= amount; super._emergencyWithdraw(_staker); user.subVaultRewards = 0; } /** * @inheritdoc HighStreetPoolBase * * @dev Additionally to the parent smart contract, processes vault rewards of the holder, * and for HIGH pool updates (increases) pool token reserve (pool tokens value available in the pool) */ function _processRewards( address _staker, bool _withUpdate ) internal override returns (uint256 pendingYield) { _processVaultRewards(_staker); pendingYield = super._processRewards(_staker, _withUpdate); // update `poolTokenReserve` only if this is a HIGH Core Pool if (poolToken == HIGH) { poolTokenReserve += pendingYield; } } /** * @dev Used internally to process vault rewards for the staker * * @param _staker address of the user (staker) to process rewards for */ function _processVaultRewards(address _staker) private { User storage user = users[_staker]; uint256 pendingVaultClaim = pendingVaultRewards(_staker); if (pendingVaultClaim == 0) return; // read HIGH token balance of the pool via standard ERC20 interface uint256 highBalance = IERC20(HIGH).balanceOf(address(this)); require(highBalance >= pendingVaultClaim, "contract HIGH balance too low"); // update `poolTokenReserve` only if this is a HIGH Core Pool if (poolToken == HIGH) { // protects against rounding errors poolTokenReserve -= pendingVaultClaim > poolTokenReserve ? poolTokenReserve : pendingVaultClaim; } user.subVaultRewards = weightToReward(user.totalWeight, vaultRewardsPerWeight); // transfer fails if pool HIGH balance is not enough - which is a desired behavior transferHighToken(_staker, pendingVaultClaim); emit VaultRewardsClaimed(msg.sender, _staker, pendingVaultClaim); } /** * @dev Executes SafeERC20.safeTransfer on a HIGH token * */ function transferHighToken(address _to, uint256 _value) internal { // just delegate call to the target SafeERC20.safeTransfer(IERC20(HIGH), _to, _value); } /** * @dev Executes SafeERC20.safeTransferFrom on a HIGH token * */ function transferHighTokenFrom( address _from, address _to, uint256 _value ) internal { // just delegate call to the target SafeERC20.safeTransferFrom(IERC20(HIGH), _from, _to, _value); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; /** * @title High Street Pool * * @notice An abstraction representing a pool, see HighStreetPoolBase for details * */ interface IPool { /** * @dev Deposit is a key data structure used in staking, * it represents a unit of stake with its amount, weight and term (time interval) */ struct Deposit { // @dev token amount staked uint256 tokenAmount; // @dev stake weight uint256 weight; // @dev locking period - from uint64 lockedFrom; // @dev locking period - until uint64 lockedUntil; // @dev indicates if the stake was created as a yield reward bool isYield; } // for the rest of the functions see Soldoc in HighStreetPoolBase function HIGH() external view returns (address); function poolToken() external view returns (address); function isFlashPool() external view returns (bool); function weight() external view returns (uint256); function lastYieldDistribution() external view returns (uint256); function yieldRewardsPerWeight() external view returns (uint256); function usersLockingWeight() external view returns (uint256); function pendingYieldRewards(address _user) external view returns (uint256); function balanceOf(address _user) external view returns (uint256); function getDeposit(address _user, uint256 _depositId) external view returns (Deposit memory); function getDepositsLength(address _user) external view returns (uint256); function stake( uint256 _amount, uint64 _lockedUntil ) external; function unstake( uint256 _depositId, uint256 _amount ) external; function sync() external; function processRewards() external; function setWeight(uint256 _weight) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import "./IPool.sol"; interface ICorePool is IPool { function vaultRewardsPerToken() external view returns (uint256); function poolTokenReserve() external view returns (uint256); function stakeAsPool(address _staker, uint256 _amount) external; function receiveVaultRewards(uint256 _amount) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./interfaces/IPool.sol"; /** * @title HighStreet Pool Factory * * @notice HIGH Pool Factory manages HighStreet Yield farming pools, provides a single * public interface to access the pools, provides an interface for the pools * to mint yield rewards, access pool-related info, update weights, etc. * * @notice The factory is authorized (via its owner) to register new pools, change weights * of the existing pools, removing the pools (by changing their weights to zero) * * @dev The factory requires ROLE_TOKEN_CREATOR permission on the HIGH token to mint yield * (see `mintYieldTo` function) * */ contract HighStreetPoolFactory is Ownable { /** * @dev Smart contract unique identifier, a random number * @dev Should be regenerated each time smart contact source code is changed * and changes smart contract itself is to be redeployed * @dev Generated using https://www.random.org/bytes/ */ uint256 public constant FACTORY_UID = 0x484a992416a6637667452c709058dccce100b22b278536f5a6d25a14b6a1acdb; /// @dev Link to HIGH STREET ERC20 Token instance address public immutable HIGH; /// @dev Auxiliary data structure used only in getPoolData() view function struct PoolData { // @dev pool token address (like HIGH) address poolToken; // @dev pool address (like deployed core pool instance) address poolAddress; // @dev pool weight (200 for HIGH pools, 800 for HIGH/ETH pools - set during deployment) uint256 weight; // @dev flash pool flag bool isFlashPool; } /** * @dev HIGH/block determines yield farming reward base * used by the yield pools controlled by the factory */ uint256 public highPerBlock; /** * @dev The yield is distributed proportionally to pool weights; * total weight is here to help in determining the proportion */ uint256 public totalWeight; /** * @dev HIGH/block decreases by 3% every blocks/update (set to 91252 blocks during deployment); * an update is triggered by executing `updateHighPerBlock` public function */ uint256 public immutable blocksPerUpdate; /** * @dev End block is the last block when HIGH/block can be decreased; * it is implied that yield farming stops after that block */ uint256 public endBlock; /** * @dev Each time the HIGH/block ratio gets updated, the block number * when the operation has occurred gets recorded into `lastRatioUpdate` * @dev This block number is then used to check if blocks/update `blocksPerUpdate` * has passed when decreasing yield reward by 3% */ uint256 public lastRatioUpdate; /// @dev Maps pool token address (like HIGH) -> pool address (like core pool instance) mapping(address => address) public pools; /// @dev Keeps track of registered pool addresses, maps pool address -> exists flag mapping(address => bool) public poolExists; /** * @dev Fired in createPool() and registerPool() * * @param _by an address which executed an action * @param poolToken pool token address (like HIGH) * @param poolAddress deployed pool instance address * @param weight pool weight * @param isFlashPool flag indicating if pool is a flash pool */ event PoolRegistered( address indexed _by, address indexed poolToken, address indexed poolAddress, uint256 weight, bool isFlashPool ); /** * @dev Fired in changePoolWeight() * * @param _by an address which executed an action * @param poolAddress deployed pool instance address * @param weight new pool weight */ event WeightUpdated(address indexed _by, address indexed poolAddress, uint256 weight); /** * @dev Fired in updateHighPerBlock() * * @param _by an address which executed an action * @param newHighPerBlock new HIGH/block value */ event HighRatioUpdated(address indexed _by, uint256 newHighPerBlock); /** * @dev Fired in mintYieldTo() * * @param _to an address to mint tokens to * @param amount amount of HIGH tokens to mint */ event MintYield(address indexed _to, uint256 amount); /** * @dev Creates/deploys a factory instance * * @param _high HIGH ERC20 token address * @param _highPerBlock initial HIGH/block value for rewards * @param _blocksPerUpdate how frequently the rewards gets updated (decreased by 3%), blocks * @param _initBlock block number to measure _blocksPerUpdate from * @param _endBlock block number when farming stops and rewards cannot be updated anymore */ constructor( address _high, uint256 _highPerBlock, uint256 _blocksPerUpdate, uint256 _initBlock, uint256 _endBlock ) { // verify the inputs are set require(_high != address(0) , "HIGH is invalid"); require(_highPerBlock > 0, "HIGH/block not set"); require(_blocksPerUpdate > 0, "blocks/update not set"); require(_initBlock > 0, "init block not set"); require(_endBlock > _initBlock, "invalid end block: must be greater than init block"); // save the inputs into internal state variables HIGH = _high; highPerBlock = _highPerBlock; blocksPerUpdate = _blocksPerUpdate; lastRatioUpdate = _initBlock; endBlock = _endBlock; } /** * @notice Given a pool token retrieves corresponding pool address * * @dev A shortcut for `pools` mapping * * @param poolToken pool token address (like HIGH) to query pool address for * @return pool address for the token specified */ function getPoolAddress(address poolToken) external view returns (address) { // read the mapping and return return pools[poolToken]; } /** * @notice Reads pool information for the pool defined by its pool token address, * designed to simplify integration with the front ends * * @param _poolToken pool token address to query pool information for * @return pool information packed in a PoolData struct */ function getPoolData(address _poolToken) external view returns (PoolData memory) { // get the pool address from the mapping address poolAddr = pools[_poolToken]; // throw if there is no pool registered for the token specified require(poolAddr != address(0), "pool not found"); // read pool information from the pool smart contract // via the pool interface (IPool) bool isFlashPool = IPool(poolAddr).isFlashPool(); uint256 weight = IPool(poolAddr).weight(); // create the in-memory structure and return it return PoolData({ poolToken: _poolToken, poolAddress: poolAddr, weight: weight, isFlashPool: isFlashPool }); } /** * @dev Verifies if `blocksPerUpdate` has passed since last HIGH/block * ratio update and if HIGH/block reward can be decreased by 3% * * @return true if enough time has passed and `updateHighPerBlock` can be executed */ function shouldUpdateRatio() public view returns (bool) { // if yield farming period has ended if (blockNumber() > endBlock) { // HIGH/block reward cannot be updated anymore return false; } // check if blocks/update (91252 blocks) have passed since last update return blockNumber() >= lastRatioUpdate + blocksPerUpdate; } /** * @dev Registers an already deployed pool instance within the factory * * @dev Can be executed by the pool factory owner only * * @param poolAddr address of the already deployed pool instance */ function registerPool(address poolAddr) external onlyOwner { // read pool information from the pool smart contract // via the pool interface (IPool) address poolToken = IPool(poolAddr).poolToken(); bool isFlashPool = IPool(poolAddr).isFlashPool(); uint256 weight = IPool(poolAddr).weight(); // ensure that the pool is not already registered within the factory require(pools[poolToken] == address(0), "this pool is already registered"); // create pool structure, register it within the factory pools[poolToken] = poolAddr; poolExists[poolAddr] = true; // update total pool weight of the factory totalWeight += weight; // emit an event emit PoolRegistered(msg.sender, poolToken, poolAddr, weight, isFlashPool); } /** * @notice Decreases HIGH/block reward by 3%, can be executed * no more than once per `blocksPerUpdate` blocks */ function updateHighPerBlock() external { // checks if ratio can be updated i.e. if blocks/update (91252 blocks) have passed require(shouldUpdateRatio(), "too frequent"); // decreases HIGH/block reward by 3% highPerBlock = (highPerBlock * 97) / 100; // set current block as the last ratio update block lastRatioUpdate = blockNumber(); // emit an event emit HighRatioUpdated(msg.sender, highPerBlock); } /** * @dev Mints HIGH tokens; executed by HIGH Pool only * * @dev Requires factory to have ROLE_TOKEN_CREATOR permission * on the HIGH ERC20 token instance * * @param _to an address to mint tokens to * @param _amount amount of HIGH tokens to mint */ function mintYieldTo(address _to, uint256 _amount) external { // verify that sender is a pool registered withing the factory require(poolExists[msg.sender], "access denied"); // transfer HIGH tokens as required transferHighToken(_to, _amount); emit MintYield(_to, _amount); } /** * @dev Changes the weight of the pool; * executed by the pool itself or by the factory owner * * @param poolAddr address of the pool to change weight for * @param weight new weight value to set to */ function changePoolWeight(address poolAddr, uint256 weight) external { // verify function is executed either by factory owner or by the pool itself require(msg.sender == owner() || poolExists[msg.sender]); // recalculate total weight totalWeight = totalWeight + weight - IPool(poolAddr).weight(); // set the new pool weight IPool(poolAddr).setWeight(weight); // emit an event emit WeightUpdated(msg.sender, poolAddr, weight); } /** * @dev Testing time-dependent functionality is difficult and the best way of * doing it is to override block number in helper test smart contracts * * @return `block.number` in mainnet, custom values in testnets (if overridden) */ function blockNumber() public view virtual returns (uint256) { // return current block number return block.number; } /** * @dev Executes SafeERC20.safeTransfer on a HIGH token * */ function transferHighToken(address _to, uint256 _value) internal { // just delegate call to the target SafeERC20.safeTransfer(IERC20(HIGH), _to, _value); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./interfaces/IPool.sol"; import "./interfaces/ICorePool.sol"; import "./HighStreetPoolFactory.sol"; /** * @title HighStreet Pool Base * * @notice An abstract contract containing common logic for a core pool (permanent pool like HIGH/ETH or HIGH pool) * * @dev Deployment and initialization. * Any pool deployed must be bound to the deployed pool factory (HighStreetPoolFactory) * Additionally, 3 token instance addresses must be defined on deployment: * - HIGH token address * - pool token address, it can be HIGH token address, HIGH/ETH pair address, and others * * @dev Pool weight defines the fraction of the yield current pool receives among the other pools, * pool factory is responsible for the weight synchronization between the pools. * @dev The weight is logically 20% for HIGH pool and 80% for HIGH/ETH pool. * Since Solidity doesn't support fractions the weight is defined by the division of * pool weight by total pools weight (sum of all registered pools within the factory) * @dev For HIGH Pool we use 200 as weight and for HIGH/ETH pool - 800. * */ abstract contract HighStreetPoolBase is IPool, ReentrancyGuard { /// @dev Data structure representing token holder using a pool struct User { // @dev Total staked amount uint256 tokenAmount; // @dev Total reward amount uint256 rewardAmount; // @dev Total weight uint256 totalWeight; // @dev Auxiliary variable for yield calculation uint256 subYieldRewards; // @dev Auxiliary variable for vault rewards calculation uint256 subVaultRewards; // @dev An array of holder's deposits Deposit[] deposits; } /// @dev Link to HIGH STREET ERC20 Token instance address public immutable override HIGH; /// @dev Token holder storage, maps token holder address to their data record mapping(address => User) public users; /// @dev Link to the pool factory HighStreetPoolFactory instance HighStreetPoolFactory public immutable factory; /// @dev Link to the pool token instance, for example HIGH or HIGH/ETH pair address public immutable override poolToken; /// @dev Pool weight, 200 for HIGH pool or 800 for HIGH/ETH uint256 public override weight; /// @dev Block number of the last yield distribution event uint256 public override lastYieldDistribution; /// @dev Used to calculate yield rewards /// @dev This value is different from "reward per token" used in locked pool /// @dev Note: stakes are different in duration and "weight" reflects that uint256 public override yieldRewardsPerWeight; /// @dev Used to calculate yield rewards, keeps track of the tokens weight locked in staking uint256 public override usersLockingWeight; /** * @dev Stake weight is proportional to deposit amount and time locked, precisely * "deposit amount wei multiplied by (fraction of the year locked plus one)" * @dev To avoid significant precision loss due to multiplication by "fraction of the year" [0, 1], * weight is stored multiplied by 1e24 constant, as an integer * @dev Corner case 1: if time locked is zero, weight is deposit amount multiplied by 1e24 * @dev Corner case 2: if time locked is one year, fraction of the year locked is one, and * weight is a deposit amount multiplied by 2 * 1e24 */ uint256 internal constant WEIGHT_MULTIPLIER = 1e24; /** * @dev When we know beforehand that staking is done for a year, and fraction of the year locked is one, * we use simplified calculation and use the following constant instead previos one */ uint256 internal constant YEAR_STAKE_WEIGHT_MULTIPLIER = 2 * WEIGHT_MULTIPLIER; /** * @dev Rewards per weight are stored multiplied by 1e48, as integers. */ uint256 internal constant REWARD_PER_WEIGHT_MULTIPLIER = 1e48; /** * @dev We want to get deposits batched but not one by one, thus here is define the size of each batch. */ uint256 internal constant DEPOSIT_BATCH_SIZE = 20; /** * @dev Fired in _stake() and stake() * * @param _by an address which performed an operation, usually token holder * @param _from token holder address, the tokens will be returned to that address * @param amount amount of tokens staked */ event Staked(address indexed _by, address indexed _from, uint256 amount); /** * @dev Fired in _updateStakeLock() and updateStakeLock() * * @param _by an address which performed an operation * @param depositId updated deposit ID * @param lockedFrom deposit locked from value * @param lockedUntil updated deposit locked until value */ event StakeLockUpdated(address indexed _by, uint256 depositId, uint64 lockedFrom, uint64 lockedUntil); /** * @dev Fired in _unstake() and unstake() * * @param _by an address which performed an operation, usually token holder * @param _to an address which received the unstaked tokens, usually token holder * @param amount amount of tokens unstaked */ event Unstaked(address indexed _by, address indexed _to, uint256 amount); /** * @dev Fired in _sync(), sync() and dependent functions (stake, unstake, etc.) * * @param _by an address which performed an operation * @param yieldRewardsPerWeight updated yield rewards per weight value * @param lastYieldDistribution usually, current block number */ event Synchronized(address indexed _by, uint256 yieldRewardsPerWeight, uint256 lastYieldDistribution); /** * @dev Fired in _processRewards(), processRewards() and dependent functions (stake, unstake, etc.) * * @param _by an address which performed an operation * @param _to an address which claimed the yield reward * @param amount amount of yield paid */ event YieldClaimed(address indexed _by, address indexed _to, uint256 amount); /** * @dev Fired in setWeight() * * @param _fromVal old pool weight value * @param _toVal new pool weight value */ event PoolWeightUpdated(uint256 _fromVal, uint256 _toVal); /** * @dev Fired in _emergencyWithdraw() * * @param _by an address which performed an operation, usually token holder * @param amount amount of tokens withdraw */ event EmergencyWithdraw(address indexed _by, uint256 amount); /** * @dev Overridden in sub-contracts to construct the pool * * @param _high HIGH ERC20 Token IlluviumERC20 address * @param _factory Pool factory HighStreetPoolFactory instance/address * @param _poolToken token the pool operates on, for example HIGH or HIGH/ETH pair * @param _initBlock initial block used to calculate the rewards * note: _initBlock can be set to the future effectively meaning _sync() calls will do nothing * @param _weight number representing a weight of the pool, actual weight fraction * is calculated as that number divided by the total pools weight and doesn't exceed one */ constructor( address _high, HighStreetPoolFactory _factory, address _poolToken, uint256 _initBlock, uint256 _weight ) { // verify the inputs are set require(_high != address(0), "high token address not set"); require(address(_factory) != address(0), "HIGH Pool fct address not set"); require(_poolToken != address(0), "pool token address not set"); require(_initBlock >= blockNumber(), "Invalid init block"); require(_weight > 0, "pool weight not set"); // verify HighStreetPoolFactory instance supplied require( _factory.FACTORY_UID() == 0x484a992416a6637667452c709058dccce100b22b278536f5a6d25a14b6a1acdb, "unexpected FACTORY_UID" ); // save the inputs into internal state variables HIGH = _high; factory = _factory; poolToken = _poolToken; weight = _weight; // init the dependent internal state variables lastYieldDistribution = _initBlock; } /** * @notice Calculates current yield rewards value available for address specified * * @param _staker an address to calculate yield rewards value for * @return calculated yield reward value for the given address */ function pendingYieldRewards(address _staker) external view override returns (uint256) { // `newYieldRewardsPerWeight` will store stored or recalculated value for `yieldRewardsPerWeight` uint256 newYieldRewardsPerWeight; // if smart contract state was not updated recently, `yieldRewardsPerWeight` value // is outdated and we need to recalculate it in order to calculate pending rewards correctly if (blockNumber() > lastYieldDistribution && usersLockingWeight != 0) { uint256 endBlock = factory.endBlock(); uint256 multiplier = blockNumber() > endBlock ? endBlock - lastYieldDistribution : blockNumber() - lastYieldDistribution; uint256 highRewards = (multiplier * weight * factory.highPerBlock()) / factory.totalWeight(); // recalculated value for `yieldRewardsPerWeight` newYieldRewardsPerWeight = rewardToWeight(highRewards, usersLockingWeight) + yieldRewardsPerWeight; } else { // if smart contract state is up to date, we don't recalculate newYieldRewardsPerWeight = yieldRewardsPerWeight; } // based on the rewards per weight value, calculate pending rewards; User memory user = users[_staker]; uint256 pending = weightToReward(user.totalWeight, newYieldRewardsPerWeight) - user.subYieldRewards; return pending; } /** * @notice Returns total staked token balance for the given address * * @param _user an address to query balance for * @return total staked token balance */ function balanceOf(address _user) external view override returns (uint256) { // read specified user token amount and return return users[_user].tokenAmount; } /** * @notice Returns information on the given deposit for the given address * * @dev See getDepositsLength * * @param _user an address to query deposit for * @param _depositId zero-indexed deposit ID for the address specified * @return deposit info as Deposit structure */ function getDeposit(address _user, uint256 _depositId) external view override returns (Deposit memory) { // read deposit at specified index and return return users[_user].deposits[_depositId]; } /** * @notice Returns a batch of deposits on the given pageId for the given address * * @dev we separate deposits into serveral of pages, and each page have DEPOSIT_BATCH_SIZE of item. * * @param _user an address to query deposit for * @param _pageId zero-indexed page ID for the address specified * @return deposits info as Deposit structure */ function getDepositsBatch(address _user, uint256 _pageId) external view returns (Deposit[] memory) { uint256 pageStart = _pageId * DEPOSIT_BATCH_SIZE; uint256 pageEnd = (_pageId + 1) * DEPOSIT_BATCH_SIZE; uint256 pageLength = DEPOSIT_BATCH_SIZE; if(pageEnd > (users[_user].deposits.length - pageStart)) { pageEnd = users[_user].deposits.length; pageLength = pageEnd - pageStart; } Deposit[] memory deposits = new Deposit[](pageLength); for(uint256 i = pageStart; i < pageEnd; i++) { deposits[i-pageStart] = users[_user].deposits[i]; } return deposits; } /** * @notice Returns number of pages for the given address. Allows iteration over deposits. * * @dev See getDepositsBatch * * @param _user an address to query deposit length for * @return number of pages for the given address */ function getDepositsBatchLength(address _user) external view returns (uint256) { if(users[_user].deposits.length == 0) { return 0; } return 1 + (users[_user].deposits.length - 1) / DEPOSIT_BATCH_SIZE; } /** * @notice Returns number of deposits for the given address. Allows iteration over deposits. * * @dev See getDeposit * * @param _user an address to query deposit length for * @return number of deposits for the given address */ function getDepositsLength(address _user) external view override returns (uint256) { // read deposits array length and return return users[_user].deposits.length; } /** * @notice Stakes specified amount of tokens for the specified amount of time, * and pays pending yield rewards if any * * @dev Requires amount to stake to be greater than zero * * @dev Reentrancy safety enforced via `ReentrancyGuard.nonReentrant` * * @param _amount amount of tokens to stake * @param _lockUntil stake period as unix timestamp; zero means no locking */ function stake ( uint256 _amount, uint64 _lockUntil ) external override nonReentrant { // delegate call to an internal function _stake(msg.sender, _amount, _lockUntil); } /** * @notice Unstakes specified amount of tokens, and pays pending yield rewards if any * * @dev Requires amount to unstake to be greater than zero * * @dev Reentrancy safety enforced via `ReentrancyGuard.nonReentrant` * * @param _depositId deposit ID to unstake from, zero-indexed * @param _amount amount of tokens to unstake */ function unstake( uint256 _depositId, uint256 _amount ) external override nonReentrant { // delegate call to an internal function _unstake(msg.sender, _depositId, _amount); } /** * @notice Extends locking period for a given deposit * * @dev Requires new lockedUntil value to be: * higher than the current one, and * in the future, but * no more than 1 year in the future * * @dev Reentrancy safety enforced via `ReentrancyGuard.nonReentrant` * * @param depositId updated deposit ID * @param lockedUntil updated deposit locked until value */ function updateStakeLock( uint256 depositId, uint64 lockedUntil ) external nonReentrant { require(users[msg.sender].deposits[depositId].tokenAmount > 0, "Invalid amount"); // sync and call processRewards _sync(); _processRewards(msg.sender, false); // delegate call to an internal function _updateStakeLock(msg.sender, depositId, lockedUntil); } /** * @notice Service function to synchronize pool state with current time * * @dev Can be executed by anyone at any time, but has an effect only when * at least one block passes between synchronizations * @dev Executed internally when staking, unstaking, processing rewards in order * for calculations to be correct and to reflect state progress of the contract * @dev When timing conditions are not met (executed too frequently, or after factory * end block), function doesn't throw and exits silently */ function sync() external override { // delegate call to an internal function _sync(); } /** * @notice Service function to calculate and pay pending yield rewards to the sender * * @dev Can be executed by anyone at any time, but has an effect only when * executed by deposit holder and when at least one block passes from the * previous reward processing * @dev Executed internally when staking and unstaking, executes sync() under the hood * before making further calculations and payouts * @dev When timing conditions are not met (executed too frequently, or after factory * end block), function doesn't throw and exits silently * * @dev Reentrancy safety enforced via `ReentrancyGuard.nonReentrant` * */ function processRewards() external virtual override nonReentrant { // delegate call to an internal function _processRewards(msg.sender, true); } /** * @dev Executed by the factory to modify pool weight; the factory is expected * to keep track of the total pools weight when updating * * @dev Set weight to zero to disable the pool * * @param _weight new weight to set for the pool */ function setWeight(uint256 _weight) external override { // verify function is executed by the factory require(msg.sender == address(factory), "access denied"); // emit an event logging old and new weight values emit PoolWeightUpdated(weight, _weight); // set the new weight value weight = _weight; } /** * @dev Similar to public pendingYieldRewards, but performs calculations based on * current smart contract state only, not taking into account any additional * time/blocks which might have passed * * @param _staker an address to calculate yield rewards value for * @return pending calculated yield reward value for the given address */ function _pendingYieldRewards(address _staker) internal view returns (uint256 pending) { // read user data structure into memory User memory user = users[_staker]; // and perform the calculation using the values read return weightToReward(user.totalWeight, yieldRewardsPerWeight) - user.subYieldRewards; } /** * @dev Used internally, mostly by children implementations, see stake() * * @param _staker an address which stakes tokens and which will receive them back * @param _amount amount of tokens to stake * @param _lockUntil stake period as unix timestamp; zero means no locking */ function _stake( address _staker, uint256 _amount, uint64 _lockUntil ) internal virtual { // validate the inputs require(_amount > 0, "zero amount"); require( _lockUntil == 0 || (_lockUntil > now256() && _lockUntil - now256() <= 365 days), "invalid lock interval" ); // update smart contract state _sync(); // get a link to user data struct, we will write to it later User storage user = users[_staker]; // process current pending rewards if any if (user.tokenAmount > 0) { _processRewards(_staker, false); } // in most of the cases added amount `addedAmount` is simply `_amount` // however for deflationary tokens this can be different // read the current balance uint256 previousBalance = IERC20(poolToken).balanceOf(address(this)); // transfer `_amount`; note: some tokens may get burnt here transferPoolTokenFrom(msg.sender, address(this), _amount); // read new balance, usually this is just the difference `previousBalance - _amount` uint256 newBalance = IERC20(poolToken).balanceOf(address(this)); // calculate real amount taking into account deflation uint256 addedAmount = newBalance - previousBalance; // set the `lockFrom` and `lockUntil` taking into account that // zero value for `_lockUntil` means "no locking" and leads to zero values // for both `lockFrom` and `lockUntil` uint64 lockFrom = _lockUntil > 0 ? uint64(now256()) : 0; uint64 lockUntil = _lockUntil; // stake weight formula rewards for locking uint256 stakeWeight = (((lockUntil - lockFrom) * WEIGHT_MULTIPLIER) / 365 days + WEIGHT_MULTIPLIER) * addedAmount; // makes sure stakeWeight is valid require(stakeWeight > 0, "invalid stakeWeight"); // create and save the deposit (append it to deposits array) Deposit memory deposit = Deposit({ tokenAmount: addedAmount, weight: stakeWeight, lockedFrom: lockFrom, lockedUntil: lockUntil, isYield: false }); // deposit ID is an index of the deposit in `deposits` array user.deposits.push(deposit); // update user record user.tokenAmount += addedAmount; user.totalWeight += stakeWeight; user.subYieldRewards = weightToReward(user.totalWeight, yieldRewardsPerWeight); // update global variable usersLockingWeight += stakeWeight; // emit an event emit Staked(msg.sender, _staker, addedAmount); } /** * @dev Used internally, mostly by children implementations, see unstake() * * @param _staker an address which unstakes tokens (which previously staked them) * @param _depositId deposit ID to unstake from, zero-indexed * @param _amount amount of tokens to unstake */ function _unstake( address _staker, uint256 _depositId, uint256 _amount ) internal virtual { // verify an amount is set require(_amount > 0, "zero amount"); // get a link to user data struct, we will write to it later User storage user = users[_staker]; // get a link to the corresponding deposit, we may write to it later Deposit storage stakeDeposit = user.deposits[_depositId]; // deposit structure may get deleted, so we save isYield flag to be able to use it bool isYield = stakeDeposit.isYield; // verify available balance // if staker address ot deposit doesn't exist this check will fail as well require(stakeDeposit.tokenAmount >= _amount, "amount exceeds stake"); // update smart contract state _sync(); // and process current pending rewards if any _processRewards(_staker, false); // recalculate deposit weight uint256 previousWeight = stakeDeposit.weight; uint256 newWeight = (((stakeDeposit.lockedUntil - stakeDeposit.lockedFrom) * WEIGHT_MULTIPLIER) / 365 days + WEIGHT_MULTIPLIER) * (stakeDeposit.tokenAmount - _amount); // update the deposit, or delete it if its depleted if (stakeDeposit.tokenAmount - _amount == 0) { delete user.deposits[_depositId]; } else { stakeDeposit.tokenAmount -= _amount; stakeDeposit.weight = newWeight; } // update user record user.tokenAmount -= _amount; user.totalWeight = user.totalWeight - previousWeight + newWeight; user.subYieldRewards = weightToReward(user.totalWeight, yieldRewardsPerWeight); // update global variable usersLockingWeight = usersLockingWeight - previousWeight + newWeight; // if the deposit was created by the pool itself as a yield reward if (isYield) { user.rewardAmount -= _amount; // mint the yield via the factory factory.mintYieldTo(msg.sender, _amount); } else { // otherwise just return tokens back to holder transferPoolToken(msg.sender, _amount); } // emit an event emit Unstaked(msg.sender, _staker, _amount); } /** * @notice Emergency withdraw specified amount of tokens * * * @dev Reentrancy safety enforced via `ReentrancyGuard.nonReentrant` * */ function emergencyWithdraw() external nonReentrant { require(factory.totalWeight() == 0, "totalWeight != 0"); // delegate call to an internal function _emergencyWithdraw(msg.sender); } /** * @dev Used internally, mostly by children implementations, see emergencyWithdraw() * * @param _staker an address which unstakes tokens (which previously staked them) */ function _emergencyWithdraw( address _staker ) internal virtual { // get a link to user data struct, we will write to it later User storage user = users[_staker]; uint256 totalWeight = user.totalWeight ; uint256 amount = user.tokenAmount; uint256 reward = user.rewardAmount; // update user record user.tokenAmount = 0; user.rewardAmount = 0; user.totalWeight = 0; user.subYieldRewards = 0; // delete entire array directly delete user.deposits; // update global variable usersLockingWeight = usersLockingWeight - totalWeight; // just return tokens back to holder transferPoolToken(msg.sender, amount - reward); // mint the yield via the factory factory.mintYieldTo(msg.sender, reward); emit EmergencyWithdraw(msg.sender, amount); } /** * @dev Used internally, mostly by children implementations, see sync() * * @dev Updates smart contract state (`yieldRewardsPerWeight`, `lastYieldDistribution`), * updates factory state via `updatehighPerBlock` */ function _sync() internal virtual { // update HIGH per block value in factory if required if (factory.shouldUpdateRatio()) { factory.updateHighPerBlock(); } // check bound conditions and if these are not met - // exit silently, without emitting an event uint256 endBlock = factory.endBlock(); if (lastYieldDistribution >= endBlock) { return; } if (blockNumber() <= lastYieldDistribution) { return; } // if locking weight is zero - update only `lastYieldDistribution` and exit if (usersLockingWeight == 0) { lastYieldDistribution = blockNumber(); return; } // to calculate the reward we need to know how many blocks passed, and reward per block uint256 currentBlock = blockNumber() > endBlock ? endBlock : blockNumber(); uint256 blocksPassed = currentBlock - lastYieldDistribution; uint256 highPerBlock = factory.highPerBlock(); // calculate the reward uint256 highReward = (blocksPassed * highPerBlock * weight) / factory.totalWeight(); // update rewards per weight and `lastYieldDistribution` yieldRewardsPerWeight += rewardToWeight(highReward, usersLockingWeight); lastYieldDistribution = currentBlock; // emit an event emit Synchronized(msg.sender, yieldRewardsPerWeight, lastYieldDistribution); } /** * @dev Used internally, mostly by children implementations, see processRewards() * * @param _staker an address which receives the reward (which has staked some tokens earlier) * @param _withUpdate flag allowing to disable synchronization (see sync()) if set to false * @return pendingYield the rewards calculated and optionally re-staked */ function _processRewards( address _staker, bool _withUpdate ) internal virtual returns (uint256 pendingYield) { // update smart contract state if required if (_withUpdate) { _sync(); } // calculate pending yield rewards, this value will be returned pendingYield = _pendingYieldRewards(_staker); // if pending yield is zero - just return silently if (pendingYield == 0) return 0; // get link to a user data structure, we will write into it later User storage user = users[_staker]; if (poolToken == HIGH) { // calculate pending yield weight, // 2e6 is the bonus weight when staking for 1 year uint256 depositWeight = pendingYield * YEAR_STAKE_WEIGHT_MULTIPLIER; // if the pool is HIGH Pool - create new HIGH deposit // and save it - push it into deposits array Deposit memory newDeposit = Deposit({ tokenAmount: pendingYield, lockedFrom: uint64(now256()), lockedUntil: uint64(now256() + 365 days), // staking yield for 1 year weight: depositWeight, isYield: true }); user.deposits.push(newDeposit); // update user record user.tokenAmount += pendingYield; user.rewardAmount += pendingYield; user.totalWeight += depositWeight; // update global variable usersLockingWeight += depositWeight; } else { // for other pools - stake as pool address highPool = factory.getPoolAddress(HIGH); require(highPool != address(0),"invalid high pool address"); ICorePool(highPool).stakeAsPool(_staker, pendingYield); } // update users's record for `subYieldRewards` if requested if (_withUpdate) { user.subYieldRewards = weightToReward(user.totalWeight, yieldRewardsPerWeight); } // emit an event emit YieldClaimed(msg.sender, _staker, pendingYield); } /** * @dev See updateStakeLock() * * @param _staker an address to update stake lock * @param _depositId updated deposit ID * @param _lockedUntil updated deposit locked until value */ function _updateStakeLock( address _staker, uint256 _depositId, uint64 _lockedUntil ) internal { // validate the input time require(_lockedUntil > now256(), "lock should be in the future"); // get a link to user data struct, we will write to it later User storage user = users[_staker]; // get a link to the corresponding deposit, we may write to it later Deposit storage stakeDeposit = user.deposits[_depositId]; // validate the input against deposit structure require(_lockedUntil > stakeDeposit.lockedUntil, "invalid new lock"); // verify locked from and locked until values if (stakeDeposit.lockedFrom == 0) { require(_lockedUntil - now256() <= 365 days, "max lock period is 365 days"); stakeDeposit.lockedFrom = uint64(now256()); } else { require(_lockedUntil - stakeDeposit.lockedFrom <= 365 days, "max lock period is 365 days"); } // update locked until value, calculate new weight stakeDeposit.lockedUntil = _lockedUntil; uint256 newWeight = (((stakeDeposit.lockedUntil - stakeDeposit.lockedFrom) * WEIGHT_MULTIPLIER) / 365 days + WEIGHT_MULTIPLIER) * stakeDeposit.tokenAmount; // save previous weight uint256 previousWeight = stakeDeposit.weight; // update weight stakeDeposit.weight = newWeight; // update user total weight and global locking weight user.totalWeight = user.totalWeight - previousWeight + newWeight; usersLockingWeight = usersLockingWeight - previousWeight + newWeight; // emit an event emit StakeLockUpdated(_staker, _depositId, stakeDeposit.lockedFrom, _lockedUntil); } /** * @dev Converts stake weight (not to be mixed with the pool weight) to * HIGH reward value, applying the 10^48 division on weight * * @param _weight stake weight * @param rewardPerWeight HIGH reward per weight * @return reward value normalized to 10^48 */ function weightToReward(uint256 _weight, uint256 rewardPerWeight) public pure returns (uint256) { // apply the formula and return return (_weight * rewardPerWeight) / REWARD_PER_WEIGHT_MULTIPLIER; } /** * @dev Converts reward HIGH value to stake weight (not to be mixed with the pool weight), * applying the 10^12 multiplication on the reward * - OR - * @dev Converts reward HIGH value to reward/weight if stake weight is supplied as second * function parameter instead of reward/weight * * @param reward yield reward * @param rewardPerWeight reward/weight (or stake weight) * @return stake weight (or reward/weight) */ function rewardToWeight(uint256 reward, uint256 rewardPerWeight) public pure returns (uint256) { // apply the reverse formula and return return (reward * REWARD_PER_WEIGHT_MULTIPLIER) / rewardPerWeight; } /** * @dev Testing time-dependent functionality is difficult and the best way of * doing it is to override block number in helper test smart contracts * * @return `block.number` in mainnet, custom values in testnets (if overridden) */ function blockNumber() public view virtual returns (uint256) { // return current block number return block.number; } /** * @dev Testing time-dependent functionality is difficult and the best way of * doing it is to override time in helper test smart contracts * * @return `block.timestamp` in mainnet, custom values in testnets (if overridden) */ function now256() public view virtual returns (uint256) { // return current block timestamp return block.timestamp; } /** * @dev Executes SafeERC20.safeTransfer on a pool token * */ function transferPoolToken(address _to, uint256 _value) internal { SafeERC20.safeTransfer(IERC20(poolToken), _to, _value); } /** * @dev Executes SafeERC20.safeTransferFrom on a pool token * */ function transferPoolTokenFrom( address _from, address _to, uint256 _value ) internal { SafeERC20.safeTransferFrom(IERC20(poolToken), _from, _to, _value); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 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 functionCall(target, data, "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"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(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) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason 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 { // 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.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)); } } /** * @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 pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount ) external returns (bool); /** * @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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT 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() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { 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 { _setOwner(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"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
{ "remappings": [], "optimizer": { "enabled": true, "runs": 10000 }, "evmVersion": "london", "libraries": {}, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_high","type":"address"},{"internalType":"contract HighStreetPoolFactory","name":"_factory","type":"address"},{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"uint256","name":"_initBlock","type":"uint256"},{"internalType":"uint256","name":"_weight","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_fromVal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toVal","type":"uint256"}],"name":"PoolWeightUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"lockedFrom","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"lockedUntil","type":"uint64"}],"name":"StakeLockUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":false,"internalType":"uint256","name":"yieldRewardsPerWeight","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastYieldDistribution","type":"uint256"}],"name":"Synchronized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VaultRewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VaultRewardsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":false,"internalType":"address","name":"_fromVal","type":"address"},{"indexed":false,"internalType":"address","name":"_toVal","type":"address"}],"name":"VaultUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_by","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"YieldClaimed","type":"event"},{"inputs":[],"name":"HIGH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract HighStreetPoolFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_depositId","type":"uint256"}],"name":"getDeposit","outputs":[{"components":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint64","name":"lockedFrom","type":"uint64"},{"internalType":"uint64","name":"lockedUntil","type":"uint64"},{"internalType":"bool","name":"isYield","type":"bool"}],"internalType":"struct IPool.Deposit","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_pageId","type":"uint256"}],"name":"getDepositsBatch","outputs":[{"components":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint64","name":"lockedFrom","type":"uint64"},{"internalType":"uint64","name":"lockedUntil","type":"uint64"},{"internalType":"bool","name":"isYield","type":"bool"}],"internalType":"struct IPool.Deposit[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getDepositsBatchLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getDepositsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFlashPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastYieldDistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"now256","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"pendingVaultRewards","outputs":[{"internalType":"uint256","name":"pending","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"pendingYieldRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolTokenReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"processRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_rewardsAmount","type":"uint256"}],"name":"receiveVaultRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"rewardPerWeight","type":"uint256"}],"name":"rewardToWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"setVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_weight","type":"uint256"}],"name":"setWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint64","name":"_lockUntil","type":"uint64"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeAsPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"depositId","type":"uint256"},{"internalType":"uint64","name":"lockedUntil","type":"uint64"}],"name":"updateStakeLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"users","outputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"uint256","name":"totalWeight","type":"uint256"},{"internalType":"uint256","name":"subYieldRewards","type":"uint256"},{"internalType":"uint256","name":"subVaultRewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usersLockingWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultRewardsPerWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_weight","type":"uint256"},{"internalType":"uint256","name":"rewardPerWeight","type":"uint256"}],"name":"weightToReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"yieldRewardsPerWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60e06040523480156200001157600080fd5b50604051620040ca380380620040ca8339810160408190526200003491620002fc565b600160005584848484846001600160a01b0385166200009a5760405162461bcd60e51b815260206004820152601a60248201527f6869676820746f6b656e2061646472657373206e6f742073657400000000000060448201526064015b60405180910390fd5b6001600160a01b038416620000f25760405162461bcd60e51b815260206004820152601d60248201527f4849474820506f6f6c206663742061646472657373206e6f7420736574000000604482015260640162000091565b6001600160a01b0383166200014a5760405162461bcd60e51b815260206004820152601a60248201527f706f6f6c20746f6b656e2061646472657373206e6f7420736574000000000000604482015260640162000091565b43821015620001915760405162461bcd60e51b8152602060048201526012602482015271496e76616c696420696e697420626c6f636b60701b604482015260640162000091565b60008111620001e35760405162461bcd60e51b815260206004820152601360248201527f706f6f6c20776569676874206e6f742073657400000000000000000000000000604482015260640162000091565b836001600160a01b031663f70b7fce6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000222573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000248919062000361565b7f484a992416a6637667452c709058dccce100b22b278536f5a6d25a14b6a1acdb14620002b85760405162461bcd60e51b815260206004820152601660248201527f756e657870656374656420464143544f52595f55494400000000000000000000604482015260640162000091565b6001600160a01b0394851660805292841660a052921660c052600255600355506200037b9350505050565b6001600160a01b0381168114620002f957600080fd5b50565b600080600080600060a086880312156200031557600080fd5b85516200032281620002e3565b60208701519095506200033581620002e3565b60408701519094506200034881620002e3565b6060870151608090970151959894975095949392505050565b6000602082840312156200037457600080fd5b5051919050565b60805160a05160c051613c38620004926000396000818161046301528181610d6101528181610ef801528181611c300152818161238e0152818161248f01528181612a9601528181612b470152818161353c015261356801526000818161043c01528181610854015281816109040152818161098601528181610e0d015281816111a00152818161152d015281816116a701528181611889015281816119100152818161198601528181611a5701528181611add015281816126d90152818161310d015261326f0152600081816103f401528181610d3701528181610ece01528181611c060152818161201d0152818161229d01528181612364015281816124b2015281816126ae015261330a0152613c386000f3fe608060405234801561001057600080fd5b506004361061020b5760003560e01c80639e2c8a5b1161012a578063ce111541116100bd578063fa213bd61161008c578063fc1711f211610071578063fc1711f2146104e6578063fc27076f146104f9578063fff6cae91461050c57600080fd5b8063fa213bd6146104ca578063fbfa77cf146104d357600080fd5b8063ce11154114610485578063db2e21bc1461048e578063e8d3cad514610496578063f9fc0d07146104c257600080fd5b8063b73974a1116100f9578063b73974a1146103ef578063beb0ed6c1461042e578063c45a015514610437578063cbdf382c1461045e57600080fd5b80639e2c8a5b1461035c578063a156dc281461036f578063a1aab33f14610382578063a87430ba1461038b57600080fd5b806344cc892d116101a257806370a082311161017157806370a08231146102fa5780638ce44855146103235780638e169d4714610336578063952e68cf1461034957600080fd5b806344cc892d146102c85780634ce0f9a6146102db57806357e871e7146102e15780636817031b146102e757600080fd5b80631da10d91116101de5780631da10d91146102745780632726b5061461028c57806329eb5f2c146102ac5780633021a560146102b557600080fd5b8063054723581461021057806315188a1b1461022c578063159302fe146102415780631984db9914610261575b600080fd5b61021960075481565b6040519081526020015b60405180910390f35b61023f61023a3660046137cf565b610514565b005b61025461024f366004613821565b61061b565b604051610223919061384d565b61021961026f3660046138d8565b610830565b61027c600081565b6040519015158152602001610223565b61029f61029a366004613821565b610b7d565b60405161022391906138f5565b61021960035481565b61023f6102c3366004613940565b610c52565b61023f6102d6366004613821565b610ddf565b42610219565b43610219565b61023f6102f53660046138d8565b611194565b6102196103083660046138d8565b6001600160a01b031660009081526001602052604090205490565b6102196103313660046138d8565b61134f565b610219610344366004613959565b6113b7565b61023f6103573660046137cf565b6113e9565b61023f61036a366004613959565b61144c565b61021961037d366004613959565b6114af565b61021960025481565b6103c76103993660046138d8565b6001602081905260009182526040909120805491810154600282015460038301546004909301549192909185565b604080519586526020860194909452928401919091526060830152608082015260a001610223565b6104167f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610223565b61021960055481565b6104167f000000000000000000000000000000000000000000000000000000000000000081565b6104167f000000000000000000000000000000000000000000000000000000000000000081565b61021960085481565b61023f6114d0565b6102196104a43660046138d8565b6001600160a01b031660009081526001602052604090206005015490565b61023f61160a565b61021960045481565b600654610416906001600160a01b031681565b61023f6104f4366004613940565b61169c565b6102196105073660046138d8565b611755565b61023f61187d565b6002600054141561056c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b600260009081553381526001602052604081206005018054849081106105945761059461397b565b906000526020600020906003020160000154116105f35760405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420616d6f756e740000000000000000000000000000000000006044820152606401610563565b6105fb611887565b610606336000611bed565b50610612338383611c7b565b50506001600055565b6060600061062a6014846139d9565b90506000601461063b856001613a16565b61064591906139d9565b6001600160a01b038616600090815260016020526040902060050154909150601490610672908490613a2e565b8211156106a4576001600160a01b03861660009081526001602052604090206005015491506106a18383613a2e565b90505b60008167ffffffffffffffff8111156106bf576106bf613a45565b60405190808252806020026020018201604052801561073657816020015b6040805160a0810182526000808252602080830182905292820181905260608201819052608082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816106dd5790505b509050835b83811015610823576001600160a01b03881660009081526001602052604090206005018054829081106107705761077061397b565b60009182526020918290206040805160a0810182526003939093029091018054835260018101549383019390935260029092015467ffffffffffffffff80821693830193909352680100000000000000008104909216606082015270010000000000000000000000000000000090910460ff1615156080820152826107f58784613a2e565b815181106108055761080561397b565b6020026020010181905250808061081b90613a74565b91505061073b565b5093505050505b92915050565b60008060035461083d4390565b11801561084b575060055415155b15610a4c5760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663083c63236040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d49190613aad565b905060008143116108f1576003546108ec9043613a2e565b6108fe565b6003546108fe9083613a2e565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166396c82e576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610960573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109849190613aad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630dd792a36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a069190613aad565b600254610a1390856139d9565b610a1d91906139d9565b610a279190613ac6565b9050600454610a38826005546114af565b610a429190613a16565b9350505050610a51565b506004545b6001600160a01b0383166000908152600160208181526040808420815160c0810183528154815293810154848401526002810154848301526003810154606085015260048101546080850152600581018054835181860281018601909452808452919360a08601939290879084015b82821015610b4b5760008481526020908190206040805160a08101825260038602909201805483526001808201548486015260029091015467ffffffffffffffff80821693850193909352680100000000000000008104909216606084015270010000000000000000000000000000000090910460ff16151560808301529083529092019101610ac0565b5050505081525050905060008160600151610b6a8360400151856113b7565b610b749190613a2e565b95945050505050565b6040805160a0810182526000808252602080830182905282840182905260608301829052608083018290526001600160a01b03861682526001905291909120600501805483908110610bd157610bd161397b565b60009182526020918290206040805160a0810182526003939093029091018054835260018101549383019390935260029092015467ffffffffffffffff80821693830193909352680100000000000000008104909216606082015270010000000000000000000000000000000090910460ff16151560808201529392505050565b6006546001600160a01b03163314610cac5760405162461bcd60e51b815260206004820152600d60248201527f6163636573732064656e696564000000000000000000000000000000000000006044820152606401610563565b80610cb45750565b600060055411610d065760405162461bcd60e51b815260206004820152601360248201527f7a65726f206c6f636b696e6720776569676874000000000000000000000000006044820152606401610563565b610d11333083612018565b610d1d816005546114af565b60076000828254610d2e9190613a16565b925050819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161415610da7578060086000828254610da19190613a16565b90915550505b60405181815233907fe1745dfad8f400852fcec0e4b23dabb3b55a98c67df52ee99c5385887277d72f9060200160405180910390a250565b6040517f1e1c6a070000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631e1c6a0790602401602060405180830381865afa158015610e5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e809190613b01565b610ecc5760405162461bcd60e51b815260206004820152600d60248201527f6163636573732064656e696564000000000000000000000000000000000000006044820152606401610563565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610f6d5760405162461bcd60e51b815260206004820152601360248201527f6e6f74204849474820746f6b656e20706f6f6c000000000000000000000000006044820152606401610563565b610f75611887565b6001600160a01b0382166000908152600160205260409020805415610fa157610f9f836000611bed565b505b6000610fb869d3c21bcecceda100000060026139d9565b610fc290846139d9565b905060006040518060a00160405280858152602001838152602001610fe44290565b67ffffffffffffffff168152602001611001426301e13380613a16565b67ffffffffffffffff1681526020016001151581525090508383600001600082825461102d9190613a16565b92505081905550838360010160008282546110489190613a16565b92505081905550818360020160008282546110639190613a16565b9091555050600580840180546001818101835560009283526020808420865160039094020192835585015190820155604084015160029091018054606086015160808701511515700100000000000000000000000000000000027fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff67ffffffffffffffff92831668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941692909516919091179190911792909216919091179055815484929190611140908490613a16565b9250508190555061115783600201546004546113b7565b6003840155600283015460075461116e91906113b7565b836004018190555083600860008282546111889190613a16565b90915550505050505050565b336001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112209190613b23565b6001600160a01b0316146112765760405162461bcd60e51b815260206004820152600d60248201527f6163636573732064656e696564000000000000000000000000000000000000006044820152606401610563565b6001600160a01b0381166112cc5760405162461bcd60e51b815260206004820152600a60248201527f7a65726f20696e707574000000000000000000000000000000000000000000006044820152606401610563565b600654604080516001600160a01b039283168152918316602083015233917f2afec66505e0ceed692012e3833f6609d4933ded34732135bc05f28423744065910160405180910390a2600680547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6001600160a01b03811660009081526001602052604081206005015461137757506000919050565b6001600160a01b0382166000908152600160208190526040909120600501546014916113a291613a2e565b6113ac9190613ac6565b61082a906001613a16565b600073af298d050e4395d69670b12b7f410000000000006113d883856139d9565b6113e29190613ac6565b9392505050565b6002600054141561143c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610563565b6002600055610612338383612049565b6002600054141561149f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610563565b60026000556106123383836120a3565b6000816113d873af298d050e4395d69670b12b7f41000000000000856139d9565b600260005414156115235760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610563565b60026000819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166396c82e576040518163ffffffff1660e01b8152600401602060405180830381865afa158015611589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ad9190613aad565b156115fa5760405162461bcd60e51b815260206004820152601060248201527f746f74616c57656967687420213d2030000000000000000000000000000000006044820152606401610563565b611603336121f3565b6001600055565b6002600054141561165d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610563565b600260005561166d336001611bed565b50336000908152600160205260409020600281015460075461168f91906113b7565b6004909101556001600055565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117145760405162461bcd60e51b815260206004820152600d60248201527f6163636573732064656e696564000000000000000000000000000000000000006044820152606401610563565b60025460408051918252602082018390527feccc307e0774400debaff53f391632f50be57f2e34a80bc9dd2005f05ada1822910160405180910390a1600255565b6001600160a01b0381166000908152600160208181526040808420815160c0810183528154815293810154848401526002810154848301526003810154606085015260048101546080850152600581018054835181860281018601909452808452869594929360a086019390929190879084015b828210156118545760008481526020908190206040805160a08101825260038602909201805483526001808201548486015260029091015467ffffffffffffffff80821693850193909352680100000000000000008104909216606084015270010000000000000000000000000000000090910460ff161515608083015290835290920191016117c9565b50505050815250509050806080015161187382604001516007546113b7565b6113e29190613a2e565b611885611887565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639f1dc9bd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119099190613b01565b15611982577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639bb24f426040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561196957600080fd5b505af115801561197d573d6000803e3d6000fd5b505050505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663083c63236040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a069190613aad565b90508060035410611a145750565b6003544311611a205750565b600554611a2e574360035550565b6000814311611a3d5743611a3f565b815b9050600060035482611a519190613a2e565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630dd792a36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ab3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad79190613aad565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166396c82e576040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5d9190613aad565b600254611b6a84866139d9565b611b7491906139d9565b611b7e9190613ac6565b9050611b8c816005546114af565b60046000828254611b9d9190613a16565b90915550506003849055600454604080519182526020820186905233917f36309afb5bc3cb961bad5b8ed6bac225928c484ec2bb2dde9a95506708a4fde991015b60405180910390a25050505050565b6000611bf88361223e565b611c02838361244b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316141561082a578060086000828254611c709190613a16565b909155505092915050565b428167ffffffffffffffff1611611cd45760405162461bcd60e51b815260206004820152601c60248201527f6c6f636b2073686f756c6420626520696e2074686520667574757265000000006044820152606401610563565b6001600160a01b038316600090815260016020526040812060058101805491929185908110611d0557611d0561397b565b906000526020600020906003020190508060020160089054906101000a900467ffffffffffffffff1667ffffffffffffffff168367ffffffffffffffff1611611d905760405162461bcd60e51b815260206004820152601060248201527f696e76616c6964206e6577206c6f636b000000000000000000000000000000006044820152606401610563565b600281015467ffffffffffffffff16611e45576301e13380611dbc4267ffffffffffffffff8616613a2e565b1115611e0a5760405162461bcd60e51b815260206004820152601b60248201527f6d6178206c6f636b20706572696f6420697320333635206461797300000000006044820152606401610563565b6002810180547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff16179055611ebc565b60028101546301e1338090611e649067ffffffffffffffff1685613b40565b67ffffffffffffffff161115611ebc5760405162461bcd60e51b815260206004820152601b60248201527f6d6178206c6f636b20706572696f6420697320333635206461797300000000006044820152606401610563565b60028101805467ffffffffffffffff808616680100000000000000009081027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff84168117948590558554600095909469d3c21bcecceda1000000946301e13380948694611f359490831693831693909317920416613b40565b67ffffffffffffffff16611f4991906139d9565b611f539190613ac6565b611f5d9190613a16565b611f6791906139d9565b600183018054908290556002850154919250908290611f87908390613a2e565b611f919190613a16565b60028501556005548290611fa6908390613a2e565b611fb09190613a16565b60055560028301546040805188815267ffffffffffffffff9283166020820152918716908201526001600160a01b038816907f85daa0d8a4afa74e5bd57c0f5d2cddf52920ec882a02b8d3f646c972b4cfb6b49060600160405180910390a250505050505050565b6120447f000000000000000000000000000000000000000000000000000000000000000084848461287e565b505050565b612054838383612953565b6001600160a01b0383166000908152600160205260409020600281015460075461207e91906113b7565b816004018190555082600860008282546120989190613a16565b909155505050505050565b6001600160a01b0383166000908152600160205260408120600581018054919291859081106120d4576120d461397b565b60009182526020918290206040805160a08101825260039093029091018054835260018101549383019390935260029092015467ffffffffffffffff80821693830184905268010000000000000000820416606083015260ff7001000000000000000000000000000000009091041615156080820152915015806121655750606081015167ffffffffffffffff1642115b6121b15760405162461bcd60e51b815260206004820152601860248201527f6465706f736974206e6f742079657420756e6c6f636b656400000000000000006044820152606401610563565b82600860008282546121c39190613a2e565b909155506121d49050858585612e23565b6121e482600201546007546113b7565b82600401819055505050505050565b6001600160a01b038116600090815260016020526040812080546008805492939192839290612223908490613a2e565b909155506122329050836131ca565b50600060049091015550565b6001600160a01b03811660009081526001602052604081209061226083611755565b90508061226c57505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156122ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123109190613aad565b9050818110156123625760405162461bcd60e51b815260206004820152601d60248201527f636f6e747261637420484947482062616c616e636520746f6f206c6f770000006044820152606401610563565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614156123e65760085482116123cb57816123cf565b6008545b600860008282546123e09190613a2e565b90915550505b6123f683600201546007546113b7565b60048401556124058483613305565b6040518281526001600160a01b0385169033907f291d65ce1109b491b8b6540dabe662b3478f4c808f76bb4130c3f7afa2fab59c9060200160405180910390a350505050565b6000811561245b5761245b611887565b61246483613334565b9050806124735750600061082a565b6001600160a01b038084166000908152600160205260409020907f000000000000000000000000000000000000000000000000000000000000000081167f0000000000000000000000000000000000000000000000000000000000000000909116141561267e5760006124f169d3c21bcecceda100000060026139d9565b6124fb90846139d9565b905060006040518060a0016040528085815260200183815260200161251d4290565b67ffffffffffffffff16815260200161253a426301e13380613a16565b67ffffffffffffffff9081168252600160209283018190526005870180548083018255600091825284822086516003909202019081559385015191840191909155604084015160029093018054606086015160808701511515700100000000000000000000000000000000027fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff91861668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316969095169590951717939093169190911790915584549192508591859190612622908490613a16565b925050819055508383600101600082825461263d9190613a16565b92505081905550818360020160008282546126589190613a16565b9250508190555081600560008282546126719190613a16565b9091555061281b92505050565b6040517f1228cbee0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690631228cbee90602401602060405180830381865afa158015612722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127469190613b23565b90506001600160a01b03811661279e5760405162461bcd60e51b815260206004820152601960248201527f696e76616c6964206869676820706f6f6c2061646472657373000000000000006044820152606401610563565b6040517f44cc892d0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152602482018590528216906344cc892d90604401600060405180830381600087803b15801561280157600080fd5b505af1158015612815573d6000803e3d6000fd5b50505050505b82156128375761283181600201546004546113b7565b60038201555b6040518281526001600160a01b0385169033907ff3055bc8d92d9c8d2f12b45d112dd345cd2cfd17292b8d65c5642ac6f912dfd79060200160405180910390a35092915050565b6040516001600160a01b038085166024830152831660448201526064810182905261294d9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613452565b50505050565b600082116129a35760405162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e740000000000000000000000000000000000000000006044820152606401610563565b67ffffffffffffffff811615806129e55750428167ffffffffffffffff161180156129e557506301e133806129e24267ffffffffffffffff8416613a2e565b11155b612a315760405162461bcd60e51b815260206004820152601560248201527f696e76616c6964206c6f636b20696e74657276616c00000000000000000000006044820152606401610563565b612a39611887565b6001600160a01b0383166000908152600160205260409020805415612a6557612a63846000611bed565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b099190613aad565b9050612b16333086613537565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bba9190613aad565b90506000612bc88383613a2e565b90506000808667ffffffffffffffff1611612be4576000612be6565b425b90508560008369d3c21bcecceda10000006301e1338081612c078787613b40565b67ffffffffffffffff16612c1b91906139d9565b612c259190613ac6565b612c2f9190613a16565b612c3991906139d9565b905060008111612c8b5760405162461bcd60e51b815260206004820152601360248201527f696e76616c6964207374616b65576569676874000000000000000000000000006044820152606401610563565b6040805160a081018252858152602080820184815267ffffffffffffffff8088169484019485528681166060850190815260006080860181815260058f018054600181810183559184529683208851600390980201968755945194860194909455955160029094018054915193511515700100000000000000000000000000000000027fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff94841668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316959093169490941717919091161790558854909186918a9190612d85908490613a16565b9250508190555081886002016000828254612da09190613a16565b92505081905550612db788600201546004546113b7565b88600301819055508160056000828254612dd19190613a16565b90915550506040518581526001600160a01b038c169033907f5dac0c1b1112564a045ba943c9d50270893e8e826c49be8e7073adc713ab7bd79060200160405180910390a35050505050505050505050565b60008111612e735760405162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e740000000000000000000000000000000000000000006044820152606401610563565b6001600160a01b038316600090815260016020526040812060058101805491929185908110612ea457612ea461397b565b6000918252602090912060039091020160028101548154919250700100000000000000000000000000000000900460ff1690841115612f255760405162461bcd60e51b815260206004820152601460248201527f616d6f756e742065786365656473207374616b650000000000000000000000006044820152606401610563565b612f2d611887565b612f38866000611bed565b5060018201548254600090612f4e908790613a2e565b600285015469d3c21bcecceda1000000906301e13380908290612f8a9067ffffffffffffffff8082169168010000000000000000900416613b40565b67ffffffffffffffff16612f9e91906139d9565b612fa89190613ac6565b612fb29190613a16565b612fbc91906139d9565b8454909150612fcc908790613a2e565b61302d57846005018781548110612fe557612fe561397b565b600091825260208220600390910201818155600181019190915560020180547fffffffffffffffffffffffffffffff000000000000000000000000000000000016905561304e565b858460000160008282546130419190613a2e565b9091555050600184018190555b858560000160008282546130629190613a2e565b909155505060028501548190613079908490613a2e565b6130839190613a16565b6002860181905560045461309791906113b7565b600386015560055481906130ac908490613a2e565b6130b69190613a16565b600555821561317657858560010160008282546130d39190613a2e565b90915550506040517fe14bdb71000000000000000000000000000000000000000000000000000000008152336004820152602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e14bdb7190604401600060405180830381600087803b15801561315957600080fd5b505af115801561316d573d6000803e3d6000fd5b50505050613180565b6131803387613563565b6040518681526001600160a01b0389169033907fd8654fcc8cf5b36d30b3f5e4688fc78118e6d68de60b9994e09902268b57c3e39060200160405180910390a35050505050505050565b6001600160a01b03811660009081526001602081905260408220600281018054825493830180548685559086905591859055600383018590559193919291613216906005860190613762565b826005546132249190613a2e565b60055561323a336132358385613a2e565b613563565b6040517fe14bdb71000000000000000000000000000000000000000000000000000000008152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e14bdb7190604401600060405180830381600087803b1580156132bb57600080fd5b505af11580156132cf573d6000803e3d6000fd5b50506040518481523392507f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd96959150602001611bde565b6133307f0000000000000000000000000000000000000000000000000000000000000000838361358a565b5050565b6001600160a01b0381166000908152600160208181526040808420815160c0810183528154815293810154848401526002810154848301526003810154606085015260048101546080850152600581018054835181860281018601909452808452869594929360a086019390929190879084015b828210156134335760008481526020908190206040805160a08101825260038602909201805483526001808201548486015260029091015467ffffffffffffffff80821693850193909352680100000000000000008104909216606084015270010000000000000000000000000000000090910460ff161515608083015290835290920191016133a8565b50505050815250509050806060015161187382604001516004546113b7565b60006134a7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166135d39092919063ffffffff16565b80519091501561204457808060200190518101906134c59190613b01565b6120445760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610563565b6120447f000000000000000000000000000000000000000000000000000000000000000084848461287e565b6133307f000000000000000000000000000000000000000000000000000000000000000083835b6040516001600160a01b0383166024820152604481018290526120449084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016128cb565b60606135e284846000856135ea565b949350505050565b6060824710156136625760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610563565b843b6136b05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610563565b600080866001600160a01b031685876040516136cc9190613b95565b60006040518083038185875af1925050503d8060008114613709576040519150601f19603f3d011682016040523d82523d6000602084013e61370e565b606091505b509150915061371e828286613729565b979650505050505050565b606083156137385750816113e2565b8251156137485782518084602001fd5b8160405162461bcd60e51b81526004016105639190613bb1565b50805460008255600302906000526020600020908101906137839190613786565b50565b5b808211156137cb57600080825560018201556002810180547fffffffffffffffffffffffffffffff0000000000000000000000000000000000169055600301613787565b5090565b600080604083850312156137e257600080fd5b82359150602083013567ffffffffffffffff8116811461380157600080fd5b809150509250929050565b6001600160a01b038116811461378357600080fd5b6000806040838503121561383457600080fd5b823561383f8161380c565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b818110156138cc576138b98385518051825260208101516020830152604081015167ffffffffffffffff808216604085015280606084015116606085015250506080810151151560808301525050565b9284019260a09290920191600101613869565b50909695505050505050565b6000602082840312156138ea57600080fd5b81356113e28161380c565b60a0810161082a82848051825260208101516020830152604081015167ffffffffffffffff808216604085015280606084015116606085015250506080810151151560808301525050565b60006020828403121561395257600080fd5b5035919050565b6000806040838503121561396c57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a1157613a116139aa565b500290565b60008219821115613a2957613a296139aa565b500190565b600082821015613a4057613a406139aa565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613aa657613aa66139aa565b5060010190565b600060208284031215613abf57600080fd5b5051919050565b600082613afc577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613b1357600080fd5b815180151581146113e257600080fd5b600060208284031215613b3557600080fd5b81516113e28161380c565b600067ffffffffffffffff83811690831681811015613b6157613b616139aa565b039392505050565b60005b83811015613b84578181015183820152602001613b6c565b8381111561294d5750506000910152565b60008251613ba7818460208701613b69565b9190910192915050565b6020815260008251806020840152613bd0816040850160208701613b69565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220588831768b81d189fc7f1c8017b4e5f71390a0ed8a5b06571472c91ba354448864736f6c634300080a003300000000000000000000000071ab77b7dbb4fa7e017bc15090b216322142028200000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202820000000000000000000000000000000000000000000000000000000000d3513800000000000000000000000000000000000000000000000000000000000000c8
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061020b5760003560e01c80639e2c8a5b1161012a578063ce111541116100bd578063fa213bd61161008c578063fc1711f211610071578063fc1711f2146104e6578063fc27076f146104f9578063fff6cae91461050c57600080fd5b8063fa213bd6146104ca578063fbfa77cf146104d357600080fd5b8063ce11154114610485578063db2e21bc1461048e578063e8d3cad514610496578063f9fc0d07146104c257600080fd5b8063b73974a1116100f9578063b73974a1146103ef578063beb0ed6c1461042e578063c45a015514610437578063cbdf382c1461045e57600080fd5b80639e2c8a5b1461035c578063a156dc281461036f578063a1aab33f14610382578063a87430ba1461038b57600080fd5b806344cc892d116101a257806370a082311161017157806370a08231146102fa5780638ce44855146103235780638e169d4714610336578063952e68cf1461034957600080fd5b806344cc892d146102c85780634ce0f9a6146102db57806357e871e7146102e15780636817031b146102e757600080fd5b80631da10d91116101de5780631da10d91146102745780632726b5061461028c57806329eb5f2c146102ac5780633021a560146102b557600080fd5b8063054723581461021057806315188a1b1461022c578063159302fe146102415780631984db9914610261575b600080fd5b61021960075481565b6040519081526020015b60405180910390f35b61023f61023a3660046137cf565b610514565b005b61025461024f366004613821565b61061b565b604051610223919061384d565b61021961026f3660046138d8565b610830565b61027c600081565b6040519015158152602001610223565b61029f61029a366004613821565b610b7d565b60405161022391906138f5565b61021960035481565b61023f6102c3366004613940565b610c52565b61023f6102d6366004613821565b610ddf565b42610219565b43610219565b61023f6102f53660046138d8565b611194565b6102196103083660046138d8565b6001600160a01b031660009081526001602052604090205490565b6102196103313660046138d8565b61134f565b610219610344366004613959565b6113b7565b61023f6103573660046137cf565b6113e9565b61023f61036a366004613959565b61144c565b61021961037d366004613959565b6114af565b61021960025481565b6103c76103993660046138d8565b6001602081905260009182526040909120805491810154600282015460038301546004909301549192909185565b604080519586526020860194909452928401919091526060830152608082015260a001610223565b6104167f00000000000000000000000071ab77b7dbb4fa7e017bc15090b216322142028281565b6040516001600160a01b039091168152602001610223565b61021960055481565b6104167f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f81565b6104167f00000000000000000000000071ab77b7dbb4fa7e017bc15090b216322142028281565b61021960085481565b61023f6114d0565b6102196104a43660046138d8565b6001600160a01b031660009081526001602052604090206005015490565b61023f61160a565b61021960045481565b600654610416906001600160a01b031681565b61023f6104f4366004613940565b61169c565b6102196105073660046138d8565b611755565b61023f61187d565b6002600054141561056c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b600260009081553381526001602052604081206005018054849081106105945761059461397b565b906000526020600020906003020160000154116105f35760405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420616d6f756e740000000000000000000000000000000000006044820152606401610563565b6105fb611887565b610606336000611bed565b50610612338383611c7b565b50506001600055565b6060600061062a6014846139d9565b90506000601461063b856001613a16565b61064591906139d9565b6001600160a01b038616600090815260016020526040902060050154909150601490610672908490613a2e565b8211156106a4576001600160a01b03861660009081526001602052604090206005015491506106a18383613a2e565b90505b60008167ffffffffffffffff8111156106bf576106bf613a45565b60405190808252806020026020018201604052801561073657816020015b6040805160a0810182526000808252602080830182905292820181905260608201819052608082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816106dd5790505b509050835b83811015610823576001600160a01b03881660009081526001602052604090206005018054829081106107705761077061397b565b60009182526020918290206040805160a0810182526003939093029091018054835260018101549383019390935260029092015467ffffffffffffffff80821693830193909352680100000000000000008104909216606082015270010000000000000000000000000000000090910460ff1615156080820152826107f58784613a2e565b815181106108055761080561397b565b6020026020010181905250808061081b90613a74565b91505061073b565b5093505050505b92915050565b60008060035461083d4390565b11801561084b575060055415155b15610a4c5760007f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b031663083c63236040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d49190613aad565b905060008143116108f1576003546108ec9043613a2e565b6108fe565b6003546108fe9083613a2e565b905060007f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b03166396c82e576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610960573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109849190613aad565b7f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b0316630dd792a36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a069190613aad565b600254610a1390856139d9565b610a1d91906139d9565b610a279190613ac6565b9050600454610a38826005546114af565b610a429190613a16565b9350505050610a51565b506004545b6001600160a01b0383166000908152600160208181526040808420815160c0810183528154815293810154848401526002810154848301526003810154606085015260048101546080850152600581018054835181860281018601909452808452919360a08601939290879084015b82821015610b4b5760008481526020908190206040805160a08101825260038602909201805483526001808201548486015260029091015467ffffffffffffffff80821693850193909352680100000000000000008104909216606084015270010000000000000000000000000000000090910460ff16151560808301529083529092019101610ac0565b5050505081525050905060008160600151610b6a8360400151856113b7565b610b749190613a2e565b95945050505050565b6040805160a0810182526000808252602080830182905282840182905260608301829052608083018290526001600160a01b03861682526001905291909120600501805483908110610bd157610bd161397b565b60009182526020918290206040805160a0810182526003939093029091018054835260018101549383019390935260029092015467ffffffffffffffff80821693830193909352680100000000000000008104909216606082015270010000000000000000000000000000000090910460ff16151560808201529392505050565b6006546001600160a01b03163314610cac5760405162461bcd60e51b815260206004820152600d60248201527f6163636573732064656e696564000000000000000000000000000000000000006044820152606401610563565b80610cb45750565b600060055411610d065760405162461bcd60e51b815260206004820152601360248201527f7a65726f206c6f636b696e6720776569676874000000000000000000000000006044820152606401610563565b610d11333083612018565b610d1d816005546114af565b60076000828254610d2e9190613a16565b925050819055507f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b03167f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b03161415610da7578060086000828254610da19190613a16565b90915550505b60405181815233907fe1745dfad8f400852fcec0e4b23dabb3b55a98c67df52ee99c5385887277d72f9060200160405180910390a250565b6040517f1e1c6a070000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b031690631e1c6a0790602401602060405180830381865afa158015610e5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e809190613b01565b610ecc5760405162461bcd60e51b815260206004820152600d60248201527f6163636573732064656e696564000000000000000000000000000000000000006044820152606401610563565b7f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b03167f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b031614610f6d5760405162461bcd60e51b815260206004820152601360248201527f6e6f74204849474820746f6b656e20706f6f6c000000000000000000000000006044820152606401610563565b610f75611887565b6001600160a01b0382166000908152600160205260409020805415610fa157610f9f836000611bed565b505b6000610fb869d3c21bcecceda100000060026139d9565b610fc290846139d9565b905060006040518060a00160405280858152602001838152602001610fe44290565b67ffffffffffffffff168152602001611001426301e13380613a16565b67ffffffffffffffff1681526020016001151581525090508383600001600082825461102d9190613a16565b92505081905550838360010160008282546110489190613a16565b92505081905550818360020160008282546110639190613a16565b9091555050600580840180546001818101835560009283526020808420865160039094020192835585015190820155604084015160029091018054606086015160808701511515700100000000000000000000000000000000027fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff67ffffffffffffffff92831668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941692909516919091179190911792909216919091179055815484929190611140908490613a16565b9250508190555061115783600201546004546113b7565b6003840155600283015460075461116e91906113b7565b836004018190555083600860008282546111889190613a16565b90915550505050505050565b336001600160a01b03167f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112209190613b23565b6001600160a01b0316146112765760405162461bcd60e51b815260206004820152600d60248201527f6163636573732064656e696564000000000000000000000000000000000000006044820152606401610563565b6001600160a01b0381166112cc5760405162461bcd60e51b815260206004820152600a60248201527f7a65726f20696e707574000000000000000000000000000000000000000000006044820152606401610563565b600654604080516001600160a01b039283168152918316602083015233917f2afec66505e0ceed692012e3833f6609d4933ded34732135bc05f28423744065910160405180910390a2600680547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6001600160a01b03811660009081526001602052604081206005015461137757506000919050565b6001600160a01b0382166000908152600160208190526040909120600501546014916113a291613a2e565b6113ac9190613ac6565b61082a906001613a16565b600073af298d050e4395d69670b12b7f410000000000006113d883856139d9565b6113e29190613ac6565b9392505050565b6002600054141561143c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610563565b6002600055610612338383612049565b6002600054141561149f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610563565b60026000556106123383836120a3565b6000816113d873af298d050e4395d69670b12b7f41000000000000856139d9565b600260005414156115235760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610563565b60026000819055507f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b03166396c82e576040518163ffffffff1660e01b8152600401602060405180830381865afa158015611589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ad9190613aad565b156115fa5760405162461bcd60e51b815260206004820152601060248201527f746f74616c57656967687420213d2030000000000000000000000000000000006044820152606401610563565b611603336121f3565b6001600055565b6002600054141561165d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610563565b600260005561166d336001611bed565b50336000908152600160205260409020600281015460075461168f91906113b7565b6004909101556001600055565b336001600160a01b037f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f16146117145760405162461bcd60e51b815260206004820152600d60248201527f6163636573732064656e696564000000000000000000000000000000000000006044820152606401610563565b60025460408051918252602082018390527feccc307e0774400debaff53f391632f50be57f2e34a80bc9dd2005f05ada1822910160405180910390a1600255565b6001600160a01b0381166000908152600160208181526040808420815160c0810183528154815293810154848401526002810154848301526003810154606085015260048101546080850152600581018054835181860281018601909452808452869594929360a086019390929190879084015b828210156118545760008481526020908190206040805160a08101825260038602909201805483526001808201548486015260029091015467ffffffffffffffff80821693850193909352680100000000000000008104909216606084015270010000000000000000000000000000000090910460ff161515608083015290835290920191016117c9565b50505050815250509050806080015161187382604001516007546113b7565b6113e29190613a2e565b611885611887565b565b7f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b0316639f1dc9bd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119099190613b01565b15611982577f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b0316639bb24f426040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561196957600080fd5b505af115801561197d573d6000803e3d6000fd5b505050505b60007f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b031663083c63236040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a069190613aad565b90508060035410611a145750565b6003544311611a205750565b600554611a2e574360035550565b6000814311611a3d5743611a3f565b815b9050600060035482611a519190613a2e565b905060007f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b0316630dd792a36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ab3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad79190613aad565b905060007f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b03166396c82e576040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5d9190613aad565b600254611b6a84866139d9565b611b7491906139d9565b611b7e9190613ac6565b9050611b8c816005546114af565b60046000828254611b9d9190613a16565b90915550506003849055600454604080519182526020820186905233917f36309afb5bc3cb961bad5b8ed6bac225928c484ec2bb2dde9a95506708a4fde991015b60405180910390a25050505050565b6000611bf88361223e565b611c02838361244b565b90507f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b03167f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b0316141561082a578060086000828254611c709190613a16565b909155505092915050565b428167ffffffffffffffff1611611cd45760405162461bcd60e51b815260206004820152601c60248201527f6c6f636b2073686f756c6420626520696e2074686520667574757265000000006044820152606401610563565b6001600160a01b038316600090815260016020526040812060058101805491929185908110611d0557611d0561397b565b906000526020600020906003020190508060020160089054906101000a900467ffffffffffffffff1667ffffffffffffffff168367ffffffffffffffff1611611d905760405162461bcd60e51b815260206004820152601060248201527f696e76616c6964206e6577206c6f636b000000000000000000000000000000006044820152606401610563565b600281015467ffffffffffffffff16611e45576301e13380611dbc4267ffffffffffffffff8616613a2e565b1115611e0a5760405162461bcd60e51b815260206004820152601b60248201527f6d6178206c6f636b20706572696f6420697320333635206461797300000000006044820152606401610563565b6002810180547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff16179055611ebc565b60028101546301e1338090611e649067ffffffffffffffff1685613b40565b67ffffffffffffffff161115611ebc5760405162461bcd60e51b815260206004820152601b60248201527f6d6178206c6f636b20706572696f6420697320333635206461797300000000006044820152606401610563565b60028101805467ffffffffffffffff808616680100000000000000009081027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff84168117948590558554600095909469d3c21bcecceda1000000946301e13380948694611f359490831693831693909317920416613b40565b67ffffffffffffffff16611f4991906139d9565b611f539190613ac6565b611f5d9190613a16565b611f6791906139d9565b600183018054908290556002850154919250908290611f87908390613a2e565b611f919190613a16565b60028501556005548290611fa6908390613a2e565b611fb09190613a16565b60055560028301546040805188815267ffffffffffffffff9283166020820152918716908201526001600160a01b038816907f85daa0d8a4afa74e5bd57c0f5d2cddf52920ec882a02b8d3f646c972b4cfb6b49060600160405180910390a250505050505050565b6120447f00000000000000000000000071ab77b7dbb4fa7e017bc15090b216322142028284848461287e565b505050565b612054838383612953565b6001600160a01b0383166000908152600160205260409020600281015460075461207e91906113b7565b816004018190555082600860008282546120989190613a16565b909155505050505050565b6001600160a01b0383166000908152600160205260408120600581018054919291859081106120d4576120d461397b565b60009182526020918290206040805160a08101825260039093029091018054835260018101549383019390935260029092015467ffffffffffffffff80821693830184905268010000000000000000820416606083015260ff7001000000000000000000000000000000009091041615156080820152915015806121655750606081015167ffffffffffffffff1642115b6121b15760405162461bcd60e51b815260206004820152601860248201527f6465706f736974206e6f742079657420756e6c6f636b656400000000000000006044820152606401610563565b82600860008282546121c39190613a2e565b909155506121d49050858585612e23565b6121e482600201546007546113b7565b82600401819055505050505050565b6001600160a01b038116600090815260016020526040812080546008805492939192839290612223908490613a2e565b909155506122329050836131ca565b50600060049091015550565b6001600160a01b03811660009081526001602052604081209061226083611755565b90508061226c57505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b0316906370a0823190602401602060405180830381865afa1580156122ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123109190613aad565b9050818110156123625760405162461bcd60e51b815260206004820152601d60248201527f636f6e747261637420484947482062616c616e636520746f6f206c6f770000006044820152606401610563565b7f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b03167f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b031614156123e65760085482116123cb57816123cf565b6008545b600860008282546123e09190613a2e565b90915550505b6123f683600201546007546113b7565b60048401556124058483613305565b6040518281526001600160a01b0385169033907f291d65ce1109b491b8b6540dabe662b3478f4c808f76bb4130c3f7afa2fab59c9060200160405180910390a350505050565b6000811561245b5761245b611887565b61246483613334565b9050806124735750600061082a565b6001600160a01b038084166000908152600160205260409020907f00000000000000000000000071ab77b7dbb4fa7e017bc15090b216322142028281167f00000000000000000000000071ab77b7dbb4fa7e017bc15090b2163221420282909116141561267e5760006124f169d3c21bcecceda100000060026139d9565b6124fb90846139d9565b905060006040518060a0016040528085815260200183815260200161251d4290565b67ffffffffffffffff16815260200161253a426301e13380613a16565b67ffffffffffffffff9081168252600160209283018190526005870180548083018255600091825284822086516003909202019081559385015191840191909155604084015160029093018054606086015160808701511515700100000000000000000000000000000000027fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff91861668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316969095169590951717939093169190911790915584549192508591859190612622908490613a16565b925050819055508383600101600082825461263d9190613a16565b92505081905550818360020160008282546126589190613a16565b9250508190555081600560008282546126719190613a16565b9091555061281b92505050565b6040517f1228cbee0000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000071ab77b7dbb4fa7e017bc15090b2163221420282811660048301526000917f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f90911690631228cbee90602401602060405180830381865afa158015612722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127469190613b23565b90506001600160a01b03811661279e5760405162461bcd60e51b815260206004820152601960248201527f696e76616c6964206869676820706f6f6c2061646472657373000000000000006044820152606401610563565b6040517f44cc892d0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152602482018590528216906344cc892d90604401600060405180830381600087803b15801561280157600080fd5b505af1158015612815573d6000803e3d6000fd5b50505050505b82156128375761283181600201546004546113b7565b60038201555b6040518281526001600160a01b0385169033907ff3055bc8d92d9c8d2f12b45d112dd345cd2cfd17292b8d65c5642ac6f912dfd79060200160405180910390a35092915050565b6040516001600160a01b038085166024830152831660448201526064810182905261294d9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613452565b50505050565b600082116129a35760405162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e740000000000000000000000000000000000000000006044820152606401610563565b67ffffffffffffffff811615806129e55750428167ffffffffffffffff161180156129e557506301e133806129e24267ffffffffffffffff8416613a2e565b11155b612a315760405162461bcd60e51b815260206004820152601560248201527f696e76616c6964206c6f636b20696e74657276616c00000000000000000000006044820152606401610563565b612a39611887565b6001600160a01b0383166000908152600160205260409020805415612a6557612a63846000611bed565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b0316906370a0823190602401602060405180830381865afa158015612ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b099190613aad565b9050612b16333086613537565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202826001600160a01b0316906370a0823190602401602060405180830381865afa158015612b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bba9190613aad565b90506000612bc88383613a2e565b90506000808667ffffffffffffffff1611612be4576000612be6565b425b90508560008369d3c21bcecceda10000006301e1338081612c078787613b40565b67ffffffffffffffff16612c1b91906139d9565b612c259190613ac6565b612c2f9190613a16565b612c3991906139d9565b905060008111612c8b5760405162461bcd60e51b815260206004820152601360248201527f696e76616c6964207374616b65576569676874000000000000000000000000006044820152606401610563565b6040805160a081018252858152602080820184815267ffffffffffffffff8088169484019485528681166060850190815260006080860181815260058f018054600181810183559184529683208851600390980201968755945194860194909455955160029094018054915193511515700100000000000000000000000000000000027fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff94841668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316959093169490941717919091161790558854909186918a9190612d85908490613a16565b9250508190555081886002016000828254612da09190613a16565b92505081905550612db788600201546004546113b7565b88600301819055508160056000828254612dd19190613a16565b90915550506040518581526001600160a01b038c169033907f5dac0c1b1112564a045ba943c9d50270893e8e826c49be8e7073adc713ab7bd79060200160405180910390a35050505050505050505050565b60008111612e735760405162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e740000000000000000000000000000000000000000006044820152606401610563565b6001600160a01b038316600090815260016020526040812060058101805491929185908110612ea457612ea461397b565b6000918252602090912060039091020160028101548154919250700100000000000000000000000000000000900460ff1690841115612f255760405162461bcd60e51b815260206004820152601460248201527f616d6f756e742065786365656473207374616b650000000000000000000000006044820152606401610563565b612f2d611887565b612f38866000611bed565b5060018201548254600090612f4e908790613a2e565b600285015469d3c21bcecceda1000000906301e13380908290612f8a9067ffffffffffffffff8082169168010000000000000000900416613b40565b67ffffffffffffffff16612f9e91906139d9565b612fa89190613ac6565b612fb29190613a16565b612fbc91906139d9565b8454909150612fcc908790613a2e565b61302d57846005018781548110612fe557612fe561397b565b600091825260208220600390910201818155600181019190915560020180547fffffffffffffffffffffffffffffff000000000000000000000000000000000016905561304e565b858460000160008282546130419190613a2e565b9091555050600184018190555b858560000160008282546130629190613a2e565b909155505060028501548190613079908490613a2e565b6130839190613a16565b6002860181905560045461309791906113b7565b600386015560055481906130ac908490613a2e565b6130b69190613a16565b600555821561317657858560010160008282546130d39190613a2e565b90915550506040517fe14bdb71000000000000000000000000000000000000000000000000000000008152336004820152602481018790527f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b03169063e14bdb7190604401600060405180830381600087803b15801561315957600080fd5b505af115801561316d573d6000803e3d6000fd5b50505050613180565b6131803387613563565b6040518681526001600160a01b0389169033907fd8654fcc8cf5b36d30b3f5e4688fc78118e6d68de60b9994e09902268b57c3e39060200160405180910390a35050505050505050565b6001600160a01b03811660009081526001602081905260408220600281018054825493830180548685559086905591859055600383018590559193919291613216906005860190613762565b826005546132249190613a2e565b60055561323a336132358385613a2e565b613563565b6040517fe14bdb71000000000000000000000000000000000000000000000000000000008152336004820152602481018290527f00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f6001600160a01b03169063e14bdb7190604401600060405180830381600087803b1580156132bb57600080fd5b505af11580156132cf573d6000803e3d6000fd5b50506040518481523392507f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd96959150602001611bde565b6133307f00000000000000000000000071ab77b7dbb4fa7e017bc15090b2163221420282838361358a565b5050565b6001600160a01b0381166000908152600160208181526040808420815160c0810183528154815293810154848401526002810154848301526003810154606085015260048101546080850152600581018054835181860281018601909452808452869594929360a086019390929190879084015b828210156134335760008481526020908190206040805160a08101825260038602909201805483526001808201548486015260029091015467ffffffffffffffff80821693850193909352680100000000000000008104909216606084015270010000000000000000000000000000000090910460ff161515608083015290835290920191016133a8565b50505050815250509050806060015161187382604001516004546113b7565b60006134a7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166135d39092919063ffffffff16565b80519091501561204457808060200190518101906134c59190613b01565b6120445760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610563565b6120447f00000000000000000000000071ab77b7dbb4fa7e017bc15090b216322142028284848461287e565b6133307f00000000000000000000000071ab77b7dbb4fa7e017bc15090b216322142028283835b6040516001600160a01b0383166024820152604481018290526120449084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016128cb565b60606135e284846000856135ea565b949350505050565b6060824710156136625760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610563565b843b6136b05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610563565b600080866001600160a01b031685876040516136cc9190613b95565b60006040518083038185875af1925050503d8060008114613709576040519150601f19603f3d011682016040523d82523d6000602084013e61370e565b606091505b509150915061371e828286613729565b979650505050505050565b606083156137385750816113e2565b8251156137485782518084602001fd5b8160405162461bcd60e51b81526004016105639190613bb1565b50805460008255600302906000526020600020908101906137839190613786565b50565b5b808211156137cb57600080825560018201556002810180547fffffffffffffffffffffffffffffff0000000000000000000000000000000000169055600301613787565b5090565b600080604083850312156137e257600080fd5b82359150602083013567ffffffffffffffff8116811461380157600080fd5b809150509250929050565b6001600160a01b038116811461378357600080fd5b6000806040838503121561383457600080fd5b823561383f8161380c565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b818110156138cc576138b98385518051825260208101516020830152604081015167ffffffffffffffff808216604085015280606084015116606085015250506080810151151560808301525050565b9284019260a09290920191600101613869565b50909695505050505050565b6000602082840312156138ea57600080fd5b81356113e28161380c565b60a0810161082a82848051825260208101516020830152604081015167ffffffffffffffff808216604085015280606084015116606085015250506080810151151560808301525050565b60006020828403121561395257600080fd5b5035919050565b6000806040838503121561396c57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a1157613a116139aa565b500290565b60008219821115613a2957613a296139aa565b500190565b600082821015613a4057613a406139aa565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613aa657613aa66139aa565b5060010190565b600060208284031215613abf57600080fd5b5051919050565b600082613afc577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613b1357600080fd5b815180151581146113e257600080fd5b600060208284031215613b3557600080fd5b81516113e28161380c565b600067ffffffffffffffff83811690831681811015613b6157613b616139aa565b039392505050565b60005b83811015613b84578181015183820152602001613b6c565b8381111561294d5750506000910152565b60008251613ba7818460208701613b69565b9190910192915050565b6020815260008251806020840152613bd0816040850160208701613b69565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220588831768b81d189fc7f1c8017b4e5f71390a0ed8a5b06571472c91ba354448864736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000071ab77b7dbb4fa7e017bc15090b216322142028200000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f00000000000000000000000071ab77b7dbb4fa7e017bc15090b21632214202820000000000000000000000000000000000000000000000000000000000d3513800000000000000000000000000000000000000000000000000000000000000c8
-----Decoded View---------------
Arg [0] : _high (address): 0x71Ab77b7dbB4fa7e017BC15090b2163221420282
Arg [1] : _factory (address): 0x03Ce1fd60c31AB8b384725bcb0d8A3A46F87E20f
Arg [2] : _poolToken (address): 0x71Ab77b7dbB4fa7e017BC15090b2163221420282
Arg [3] : _initBlock (uint256): 13848888
Arg [4] : _weight (uint256): 200
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000071ab77b7dbb4fa7e017bc15090b2163221420282
Arg [1] : 00000000000000000000000003ce1fd60c31ab8b384725bcb0d8a3a46f87e20f
Arg [2] : 00000000000000000000000071ab77b7dbb4fa7e017bc15090b2163221420282
Arg [3] : 0000000000000000000000000000000000000000000000000000000000d35138
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000c8
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $1.64 | 647,149.1219 | $1,061,324.56 |
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.